tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

commit 9f20361d0438051dd6b7f7bbcea5f885258a94bb
parent f50246c22afb005e0256a2ea0388cfb42e2e672d
Author: James Eversole <james@eversole.co>
Date:   Mon, 19 Oct 2026 07:10:57 -0500

Support native and local Arboricx module imports in the browser

Publish complete library interfaces and resolve manifest-pinned imports in both WASM backends. Retain expression scopes, support public reexports, and add page-local file imports and portable compiled-module exports.

Make all demos editable native modules, refresh their content and release assets, and simplify documentation. Validate with native identity/result oracles, Chromium and Firefox integration, 114 Node tests, generated-JS parity, and Nix flake checks.

Diffstat:
Mext/demo-site/README.md | 328+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Aext/demo-site/bundles/0a3956e0f6e794d843f56d734b14259c63a6e9ece22ec73d73f8f995f1578fa8.arboricx | 0
Aext/demo-site/bundles/10dfca05efdf0113e65f5cb77de96b5e8d768c9e9749b05cda1e344715a44230.arboricx | 0
Aext/demo-site/bundles/1f18232479e776982515edc3fe2c0f39fad79e2b428c2ff040d92edf5441ac6a.arboricx | 0
Aext/demo-site/bundles/20c71797fca0c2d7c6e1a5482da8cfce80292463cba731187645e96dc17dbe2e.arboricx | 0
Aext/demo-site/bundles/2c8f29c5e1a96eac7b6d57f6dad02f7adbfca1da93742f48c2aff3534c378284.arboricx | 0
Aext/demo-site/bundles/30715cbaf97e966bcb8ef49c9f5da1fca571308db49b103b428de713b9ad302f.arboricx | 0
Aext/demo-site/bundles/3b4474558c2336c95a122ef32c4f3070ce67b2e0491539f757594a0ac02b0c6a.arboricx | 0
Aext/demo-site/bundles/3de401378f33dd8f93e9ca11c1c2bd73a458dabcd8d631a33ba17306f83d7d3b.arboricx | 0
Aext/demo-site/bundles/3e32ef46cd9a7032469c6b004917c9b8982da95673d486a576fc31541bbe51c6.arboricx | 0
Aext/demo-site/bundles/40dfb23da91b505ea4586bbfea46a7374d299bb747796f18428de7da43fa7315.arboricx | 0
Aext/demo-site/bundles/493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5.arboricx | 0
Aext/demo-site/bundles/4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea.arboricx | 0
Aext/demo-site/bundles/5188bb1a7ede262cb63f02daadff9b827c05bd26ace2e7f23528e9dd10ba6121.arboricx | 0
Aext/demo-site/bundles/51d352cb5306a96b0275e6cf80c5a7d160e7379cf8f31aa128d96fe3e56043ff.arboricx | 0
Aext/demo-site/bundles/64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5.arboricx | 0
Aext/demo-site/bundles/679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a.arboricx | 0
Aext/demo-site/bundles/718c96fe7ab33504ece9c041f7a93dddf15b281f8dfceba84291a349e260b15f.arboricx | 0
Aext/demo-site/bundles/730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3.arboricx | 0
Aext/demo-site/bundles/7b7b8b132f1192bf4a9e379b641382167f9be38a609bdad18b144dfa85da2b3c.arboricx | 0
Aext/demo-site/bundles/7fbcf00a8412785c5c61b61c21c89d00d2597953b040faa02e6e811677b37578.arboricx | 0
Aext/demo-site/bundles/84a7479abac8663864a5615e5c0be69b6bb64530a904ab0da274bbf68b682b01.arboricx | 0
Aext/demo-site/bundles/8675a2bc53b5820d45cce64c072c55f7e03d23b1b4960a45f952fc6387023024.arboricx | 0
Aext/demo-site/bundles/8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb.arboricx | 0
Aext/demo-site/bundles/a51d9fcffd12aebc39166e2ba4e5b86896832db299f06322b7a2805bc4d57f05.arboricx | 0
Aext/demo-site/bundles/a8d7805b268f93ef72e10c7031bc709fb9924ca91b2eacdd313f70d96d254560.arboricx | 0
Aext/demo-site/bundles/aabb749e392a47605ffd08f12ec442747641d190ca2c4240f3196744f6fdbd22.arboricx | 0
Aext/demo-site/bundles/acb79eb9c2f56a18c1c740aaaee97e9e5e53f55b56602bd16a351d85cfadc192.arboricx | 0
Aext/demo-site/bundles/af2b3483281c7c4e24151956dce5d763dfe4deeb4b0ec7635a341b443b2b4584.arboricx | 0
Aext/demo-site/bundles/af66062931c5de826bd336625d53c1c354fe6cc736e56e247ae550c542f0fa8a.arboricx | 0
Aext/demo-site/bundles/b61e8d7d31f730c1e4db08c729435302e76eb911ee2c45b110f2932a60b2eb33.arboricx | 0
Aext/demo-site/bundles/b82891447d90b9c9bfeef4c8a75d15589ef008d9142e32f8694bd0ce083fb8ca.arboricx | 0
Aext/demo-site/bundles/b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368.arboricx | 0
Aext/demo-site/bundles/bd742a4ec55cf68f1f1b382979fdf6b5c098039089be16c76b4621b8ca07d9cb.arboricx | 0
Aext/demo-site/bundles/c0a9ffd923b4dd17f6c1fd105502d9e82a9064f75b6312b37c155c94a3ce73d3.arboricx | 0
Aext/demo-site/bundles/d2842a47b4f76d3d0bf86914620a33b5251319167c74873e7f630923f4b95e68.arboricx | 0
Aext/demo-site/bundles/d7105ef477224dfb10ad2773e54744cb3f87ddf304eb753d7cb9ba40ea9cc3df.arboricx | 0
Aext/demo-site/bundles/decfff4079c7c202f664a55496926cce1fcd1e9c67cf67b84718bf7d663e6f4d.arboricx | 0
Aext/demo-site/bundles/e8f5fbfbb768926c5dcc43511fed05a2436f0bf46f2a18c75408496886cb1539.arboricx | 0
Aext/demo-site/bundles/eac98c45250ba80f2331cb71128306b25bd61b4e8e3e063b9b635ec654f4d698.arboricx | 0
Aext/demo-site/bundles/ed931d1cf10921f414c7fb2e21c4ab40509d548b56ca1db1327586d90cdf6f0a.arboricx | 0
Aext/demo-site/bundles/f13735828b62a6d90e95b2964e5fdf72d4e5181aa49d48c04cf134b5606bc10e.arboricx | 0
Aext/demo-site/bundles/faea17b7579cd7193af19cb74a34266cdf8ac2d9934a24d8552dd09edd5cb4c5.arboricx | 0
Aext/demo-site/bundles/fc37dd8c558961c88211c3f4faf31bc438bcda12384f94125f563f1651e09ac9.arboricx | 0
Mext/demo-site/catalogue.json | 72+++++++++++++++++++++++++++++++++++++-----------------------------------
Mext/demo-site/demos.json | 101+++++++++++++++++++++++--------------------------------------------------------
Mext/demo-site/demos/events.tri | 18+++++++++++++-----
Mext/demo-site/demos/greet.tri | 26+++++++++++++-------------
Mext/demo-site/demos/intro.tri | 29+++++++++++++++++------------
Mext/demo-site/demos/lexer.tri | 11++++++-----
Mext/demo-site/demos/microscope.tri | 41++++++++++++++++++++---------------------
Mext/demo-site/demos/migration.tri | 18+++++++++++++-----
Mext/demo-site/demos/parser.tri | 10+++++-----
Mext/demo-site/demos/practical-support.tri | 3++-
Mext/demo-site/demos/registration.tri | 21+++++++++++++--------
Mext/demo-site/demos/rgb.tri | 25++++++++-----------------
Mext/demo-site/demos/shipping.tri | 23+++++++++++++++--------
Mext/demo-site/dist/app.js | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Mext/demo-site/dist/compiler.js | 6+++---
Mext/demo-site/dist/haskell-session.js | 28++++++++++++----------------
Aext/demo-site/dist/local-module-worker.js | 5+++++
Aext/demo-site/dist/local-modules-ui.js | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/dist/local-modules.js | 31+++++++++++++++++++++++++++++++
Aext/demo-site/dist/module-bundle.js | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/dist/module-identity.js | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/dist/module-resolver.js | 13+++++++++++++
Aext/demo-site/dist/module-stage.js | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/demo-site/dist/wasm-worker.js | 17++++++++++++++++-
Mext/demo-site/environments.json | 2+-
Mext/demo-site/index.html | 21+++++++++++++++------
Mext/demo-site/lexer-demo.json | 3++-
Mext/demo-site/packages.json | 430+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/demo-site/parser-demo.json | 3++-
Mext/demo-site/prepare-index.py | 4++--
Aext/demo-site/prepare-libraries.py | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/demo-site/prepare-showcase.py | 189+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mext/demo-site/prepare.py | 55++++++++++++++++++++++++++++++++++---------------------
Mext/demo-site/src/app.ts | 45++++++++++++++++++++++++++++++++++++++++-----
Mext/demo-site/src/compiler-protocol.ts | 4+++-
Mext/demo-site/src/compiler.ts | 6+++---
Mext/demo-site/src/haskell-session.ts | 31+++++++++++++++----------------
Aext/demo-site/src/local-module-worker.ts | 5+++++
Aext/demo-site/src/local-modules-ui.ts | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/src/local-modules.ts | 24++++++++++++++++++++++++
Aext/demo-site/src/module-bundle.ts | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/src/module-identity.ts | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/src/module-resolver.ts | 12++++++++++++
Aext/demo-site/src/module-stage.ts | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/demo-site/src/protocol.ts | 4+++-
Mext/demo-site/src/runtime-session.ts | 4+++-
Mext/demo-site/src/wasm-worker.ts | 8+++++++-
Mext/demo-site/style.css | 4++++
Mext/demo-site/test/backend-browser.mjs | 2+-
Mext/demo-site/test/backend-probe.mjs | 2+-
Mext/demo-site/test/backend-server.mjs | 25+++++++++++++++++++------
Mext/demo-site/test/draft-session.test.mjs | 4++--
Mext/demo-site/test/editable-conformance.mjs | 38+++++++++++++++++++++++++++++---------
Aext/demo-site/test/local-module-native.py | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/test/local-module-probe.mjs | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/test/local-modules.test.mjs | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/test/module-goldens.json | 18++++++++++++++++++
Aext/demo-site/test/module-probe.mjs | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/test/modules.test.mjs | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aext/demo-site/test/native-modules.py | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/demo-site/test/packages.test.mjs | 22+++++++++++++++++++---
Mext/demo-site/test/release.py | 30+++++++++++++++++++++++++++---
Mext/demo-site/test/showcase-preparation.test.mjs | 2+-
Mext/demo-site/test/site.test.mjs | 2+-
Mext/demo-site/test/zig-session-probe.mjs | 6++++--
Aext/haskell-wasm/BrowserModules.hs | 88+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mext/haskell-wasm/CompilerProbe.hs | 12+++++++++++-
Mext/haskell-wasm/README.md | 45++++++++++++++++++++++++++++-----------------
Mext/haskell-wasm/Reactor.hs | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mext/haskell-wasm/browser-page.mjs | 10+++++++---
Mext/haskell-wasm/browser-parity.mjs | 6++++--
Mext/haskell-wasm/browser-worker.mjs | 58++++++++++++++++++++++++++++++++++++++++++++--------------
Mext/haskell-wasm/browser.nix | 3++-
Mext/haskell-wasm/check-browser.mjs | 3++-
Mext/haskell-wasm/check-firefox.mjs | 3++-
Mext/haskell-wasm/prepare-compiler.mjs | 4++++
Mext/haskell-wasm/prepare-parity.mjs | 11++++++++++-
Mext/wasm/site-session.mjs | 95++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
122 files changed, 3091 insertions(+), 570 deletions(-)

diff --git a/ext/demo-site/README.md b/ext/demo-site/README.md @@ -7,7 +7,7 @@ TypeScript compiled to browser ES modules. The page flows from the hero into one editor workspace, followed by the ecosystem articles. **Start Here** loads on arrival, including when no selection fragment is present; loading verifies a package but never executes it or downloads a compiler -kit. Haskell is the initial runtime. There are no tabs or separate export page. +kit. Haskell is the initial runtime. The editor combines source, an attached expression prompt, and a single output surface in one column: source → expression → Evaluate/Stop → result. Output @@ -32,7 +32,7 @@ including with reduced-motion enabled. ## Syntax colors and bracket matching -Source, read-only tricu source, and the expression prompt distinguish comments, +Editable source, reference source, and the expression prompt distinguish comments, strings/escapes, numbers, the kernel `t`, current keywords, module directives, operators and delimiters. Definition **declaration sites** have one dedicated color, including ordinary local equations; a simple contract name after `@` or @@ -76,8 +76,8 @@ use; there is no JS execution fallback. The release packages the pinned Haskell reactor, loader, WASI shim and authenticated compiler kit under `runtime/haskell/`. Loading and structured-argument runs do not download the compiler kit. Expression evaluation loads it on demand, retaining the loaded definitions. Draft compilation checks the runtime's original compiler-bundle -identity against `compiler.json`, then resolves the selected empty, practical or -default-contract environment. Missing assets or mismatched pins are errors. +identity against `compiler.json`, then resolves explicit native imports or the +selected empty, practical or default-contract standalone environment. Missing assets or mismatched pins are errors. Zig packages a freestanding reactor and private adapter under `runtime/zig/`. It has no WASI imports. Its compiler session fetches the exact authenticated compiler bundle selected by `compiler.json`, rather than loading Haskell's @@ -110,7 +110,7 @@ or a fatal trap discards the session and requires explicit reinitialization. The Haskell binary requires WebAssembly SIMD, supported starting with Chrome 91, Firefox 89 and Safari/iOS 16.4. These are feature-support floors, not tested minimum browser versions: integration is validated in Chromium 148 and Firefox -150; Safari/iOS remain unvalidated. Older clients can explicitly select JS or +150; Safari/iOS remain unvalidated. Older clients can explicitly select Zig if Haskell initialization fails; there is no silent fallback. Haskell uses a bundled WASI shim and a nested module Worker, not browser-native WASI support. @@ -196,7 +196,7 @@ The Published packages group also contains these `0.1.0` and `0.1.1` interfaces: input. Stop retains the current cell; malformed tails/decisions halt without consuming it. Callbacks can still diverge; a remaining suffix is not success. - **tricu-patterns**: first-match predicate/action rows and thunked conditionals. - These are library callbacks, not language equation patterns or guard syntax. + These helpers dispatch through library callbacks. Unselected actions are not evaluated; a reached malformed row returns Leaf. - **arboricx-server**: the registry's routes, validation and server function, @@ -219,16 +219,18 @@ Try `"red,green,blue"`, `"red,,blue"`, `"red,"` or `"red green"`. `parseNames` requires complete input; `parsePrefix` exposes any unconsumed suffix. A comma commits to another lowercase name. Scalar records show the expected label, remaining input, consumption and commitment, or the accepted names/count. -This demo has authenticated reference source, but no browser compilation -profile: its native module imports make it **read-only**, not an editable draft. +The source is editable in place. Its manifest-pinned imports use the same native +header/resolver path as other browser modules. Try changing the lowercase range +to `65 90` to parse uppercase names, or edit a diagnostic label. **Located lexer scans** under Examples is the separate `lexer-demo` package. `scanWord` scans a lowercase ASCII prefix; `scanWhitespace` scans spaces, LF and TAB. Records show matched text, remaining input, end line/column, character offset and whether anything was consumed. Try `"hello,world"`, `"abcé"` and whitespace containing a newline/tab. Empty prefixes succeed without consuming anything; -these are prefix scans, not whole-input parsers. Its pinned native imports also -make the reference source read-only in the browser. +these scans return the matching prefix and remaining input. The source is editable: change a +predicate and evaluate again. **Restore original** returns to the authenticated +published source and behavior. To reproduce and stage this cohort locally, first build the Haskell host through Nix, then run the opt-in bounded preparation: @@ -236,15 +238,15 @@ Nix, then run the opt-in bounded preparation: ```sh nix build .# python3 ext/demo-site/prepare-showcase.py result/bin/tricu \ - --directory /tmp/arboricx-showcase --version 0.1.2 --stage-site + --directory /tmp/arboricx-showcase --version NEW_UNUSED_VERSION --stage-site # Refresh the package set under a new immutable version: python3 ext/demo-site/prepare-showcase.py result/bin/tricu \ - --directory /tmp/arboricx-showcase-next --version 0.1.3 --stage-site + --directory /tmp/arboricx-showcase-next --version ANOTHER_UNUSED_VERSION --stage-site ``` Preparation authenticates retained fixtures and requires all recorded working sources to match them. Nine library interfaces retain exact constructor/child-ID -roots from those accepted artifacts, renamed without evaluation or expansion. +roots from those accepted artifacts, with renamed exports and preserved DAGs. The two compiler packages retain their exact accepted bundle bytes. The list traversal library, formatter and parser/lexer demos compile with the authenticated shipped stable builder and pinned native dependency interfaces. Acceptance includes @@ -255,24 +257,22 @@ complete parser/lexer records. Publication and a clean indexed import must agree on every manifest before staging. Ordinary packages must fit the browser's 16 MiB/100,000-node input bounds. -The indexed compiler loads under the same package profile, with no special -name-based exception. Draft compilation separately retains a 2 MiB compiler +The indexed compiler loads under the ordinary package profile. Draft compilation separately retains a 2 MiB compiler input limit. SHA-256, streaming limits, node/export validation and loading deadlines remain enforced. Native commands use 2 GiB RTS bounds, per-command deadlines and a ten-minute whole-job deadline. The output directory retains commands, source/artifact identities and acceptance results. `--reuse-directory` permits reuse of its local CAS, while rewriting -sources and rechecking native receipts; it does not trust an old success flag. -Staging is an exclusive local administrator operation, not public-network -publication. Existing release pins cannot be replaced, all assets precede +sources and rechecking native receipts on every run. +Staging is an exclusive local administrator operation. Existing release pins cannot be replaced, all assets precede index discovery, and conflicts fail before staging. Native-prepared catalogue entries have `preparation: "native"`; `prepare.py` preserves them and -`prepare-index.py` does not assign them a browser compilation environment. +`prepare-index.py` preserves their accepted editability metadata. Current examples +use `environment: "empty"`: their native headers provide all library bindings. Existing immutable versions are unchanged. `--version` selects the exact label for the entire prepared package set (default `0.1.1`); a changed bundle cannot -replace an existing name/version. The `patterns` interface comes from the support fixture, not a -build-only edge through IO or the compiler closure. +replace an existing name/version. The `patterns` interface comes from the support fixture. ### Published packages and local drafts @@ -295,10 +295,9 @@ Single-release examples also expose their version in **Settings → Published package**, alongside verification details, the hash loader, sharing and original bundle download. Changing program, version or hash invalidates the preceding executable and output; evaluation stays disabled until verification succeeds. -Published packages can be source-free or have read-only source. Their exports -remain usable in expressions and as stored-definition output without rebuilding -or modifying the implementation. Editable demos display source directly, without -an Edit button. Until the source changes, expressions use the authenticated package's +Published packages expose their exports to expressions and stored-definition +output. Available reference source is displayed alongside them. Editable demos +open directly in the source editor. Until the source changes, expressions use the authenticated package's exports. Changing source switches to **Local draft** and queues compilation after 650 ms of idle time. **Compile now** starts immediately; neither path executes user programs. The editor remains available during compilation. Edits are @@ -320,23 +319,19 @@ Evaluation is disabled while the session is busy, including while waiting for IO Stop must precede replacement of an active attempt. Hard Stop or a fatal WASM failure loses that session's definitions, but preserves source. **Compile now** or another edit rebuilds them; Stop does not automatically restart work. -Changing backend rebuilds a draft automatically, without transferring heaps or -executing it. Scrolling to ecosystem content does not terminate a session. -An elapsed compilation indicator and Stop remain available; there are no -configurable execution limits or slow-compilation warnings. +Changing backend rebuilds a draft from its source. Sessions remain active while +scrolling through the page. An elapsed compilation indicator and Stop remain +available. **Settings → Download .arboricx** returns the original bounded, hash-verified -bytes for the selected version/hash, not an applied result or local draft. It +bytes for the selected version/hash. It verifies independently and leaves the visible result and its Copy/Download payload unchanged. Download/sharing and stored-definition output are disabled for drafts; -restore published source first. Draft package publication is not supported. +restore published source first. Use **Export compiled module** to save a draft. -Drafts exist only in the open page. There is no autosaving, browser-storage -access, saved-source download or recovery UI. Compilation failure, Stop and -backend changes retain source in the current editor; a page reload -starts fresh from its published selection (or selection link), without restoring, -compiling or running a draft. Copy important source elsewhere before leaving. -Copies stored by older site releases are ignored, not read or restored. +Draft source lives in the open page and survives compilation failure, Stop and +backend changes. Reloading starts fresh from the published selection or selection +link. Copy important source elsewhere before leaving. ### Arguments, results, and IO @@ -344,9 +339,10 @@ Copies stored by older site releases are ignored, not read or restored. `identity (first 42 7)` in the intro demo and `append "hello " "world"` in the published base library. Expressions may use literals, applications, lambdas and local bindings. Their environment contains exactly the selected package's -exports or current draft definitions, not an implicit prelude or module resolver. +exports or current draft scope (local definitions plus explicit imports). Native +modules import their prelude explicitly. Put import directives in the source editor. Read-only and source-free packages work identically: the compiler binds names to -existing trees without reconstructing source or normalizing all exports. +existing tree handles. Expressions compile only when **Evaluate** is pressed, then run in the selected pure/IO mode. A fresh, collision-free temporary definition wraps one expression; @@ -354,7 +350,9 @@ its name is never installed in the package or draft. Diagnostics map wrapper coordinates back to expression lines/columns. The wrapped source shares the 16,384-scalar source bound, so layout/wrapper overhead counts toward that bound. Expression compilation and observation do not mutate the public definition table; -stored exports/downloads always use the authenticated original bundle. +stored-definition exports and original-bundle downloads always use the +authenticated original bundle. **Export compiled module** is a separate action +for the current draft, described below. **Settings → Use structured arguments** retains the data-only input interface. Each field is one argument: `42`, `"hello"`, `[1 2 3]`, `t`, or `(t t t)`. @@ -379,8 +377,8 @@ for the literal editor. Raw kinds remain string, natural decimal string, Boolean bytes, recursively typed list, and ternary tree. Switching editors preserves valid values; invalid literal fields must be corrected before switching to raw. Partial and multiple applications are ordinary left-folded Tree Calculus application. -The authenticated packaged intro guide still describes the raw JSON argument box; -its published source and bundle identities have not been rewritten by this UI change. +The current Start Here guide uses expression input and the current result +interpretations; historical package releases retain their original content. Value interpretations include text, natural number, Boolean, bytes and scalar record. `t` can represent zero, false or an empty string/list; interpretation is @@ -469,17 +467,98 @@ These output limits remain in force independently of program execution. The editor downloads the authenticated reference compiler bundle when idle source compilation, **Compile now**, or expression evaluation needs it. It invokes -`source_unit.compileStableModuleDefinitions` with an explicit environment and a standalone source unit. There are no workspace imports or publication -operations. The packaged compiler uses stable lowering. +`source_unit.compileStableModuleDefinitions` with an explicit environment. Native +headers are interpreted by the same pinned compiler's `source_module` entrypoints. +The packaged compiler uses stable lowering. -Scratch examples: identity, checked identity, pair constructor, two dependency-ordered definitions, and a -raw `tricuIO` line-input program. Compile produces a bounded definition selector; +Scratch examples: identity, checked identity, pair constructor, two dependency-ordered definitions, +a raw `tricuIO` line-input program, and **Module imports**. Compile produces a bounded definition selector; evaluate expressions against those definitions, or use the optional structured -argument fields, with the same result/IO codecs as ordinary packages. The Worker retains compiled **handles**, never serialized program trees. -Only the result spine and up to 16 names (128 scalars each) are decoded. Program +argument fields, with the same result/IO codecs as ordinary packages. The Worker retains compiled **handles**. +Only the result spine and up to 16 local-definition names (128 scalars each) are decoded. +Native public interfaces may select/reexport up to 4,096 names. Program normalization can remain deferred until application/inspection. Parser errors retain structured numeric codes, available line/column, and bounded expected -labels/token kinds; arbitrary found/context/remainder trees are not expanded. +labels/token kinds. + +### Native manifest imports + +Choose **Module imports** under Scratch examples, or use the import snippet shown +for a selected named package. The full module-manifest hash is the source reference, +not the whole-bundle download hash: + +```tricu +!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N +!export answer + +answer = N.add 40 2 +``` + +Both Haskell and Zig support qualified imports, `!import HASH *`, explicit local +exports, `!export *`, and `!export * from HASH`, including header-only reexports. +Native modules begin with an empty environment and explicitly import their +prelude and contract helpers. Standalone scratch examples use their documented +environments. A native module requires a nonempty public interface: `!export *` +selects locals, while `!export * from HASH` selects a dependency's public interface. +Lexical access to dependency bindings requires `!import`. Duplicate imports/exports +and imported/local name collisions are errors. + +Referenced published modules are fetched on demand. `packages.json` maps each +manifest to a bundle pin; verification checks both the whole-file hash and native +indexed-import manifest identity. Closed exports contain their transitive +dependencies. Browser imports accept full manifest hashes available through the +local collection or published index. IO execution uses the browser capability +profile described above. + +The runtime retains local and imported trees, including private definitions, for +subsequent expressions. The public selector exposes declared exports. Interface +selection retains native tree handles, deferring observation until execution or +export. Each compile replaces the previous definitions and import scope; failure +clears them. Successful runs and recoverable result/IO errors preserve that scope. +Stop and backend replacement terminate it. + +Source is limited to 16,384 scalars and 16 local definitions. Header names and +qualifiers allow 128 scalars; the import scope and public interface each permit +4,096 bindings. Evaluation cost and browser memory depend on the program. + +### Local files and compiled module exports + +Under **Settings → Local modules**, choose **Open local module** to open a +`.arboricx` file locally. A separate Worker validates its bundle structure and +manifest identity. The collection shows exported names, bundle SHA-256 and a +copyable `!import MANIFEST as Local` statement. Use that statement in the source +editor, declare your exports, and compile. Qualified imports, open imports and +full reexports work as they do for published modules. + +The collection lives in page memory. Files survive Stop, program changes and +backend replacement; reloading or closing the page clears them. File validation +has a **Cancel file check** button and a 60-second deadline. + +Resolution checks the local collection first, then the published index. Local +matches resolve entirely from their retained bytes; compiler/runtime assets load +on demand. Each referenced bundle is verified against its requested manifest +inside the runtime boundary. Corrupt local bytes fail compilation. Duplicate +manifests reuse the existing entry, even when filenames or bundle hashes differ. +**Remove** discards the file and rebuilds the current draft with its dependencies +resolved again. A published copy of the same manifest can then satisfy the import. + +**Export compiled module** downloads the successfully compiled draft's public +interface. **Download .arboricx** saves the original published package. Open an +exported file in Local modules to reuse it. The file names declared exports (or +standalone unit definitions) and includes their reachable trees. Function +representations, including reachable private values, remain inspectable. These +closed executable bundles also work with the native CLI. + +Export observes all public trees using pure reduction. It may compute or diverge; +**Stop** terminates the Worker while preserving the local collection. Successful +export preserves the compiled expression scope. Export requires a complete, +acyclic shared snapshot within the size bounds. Canonical indexing preserves +sharing across exports and combines structurally identical nodes. + +Limits are 16 MiB per file, 32 local modules and 64 MiB total retained file bytes, +with the existing bundle semantics/ABI, 100,000-node and 4,096-export bounds. +Compiled export's 100,000-node snapshot includes its temporary export-list spine. +Browser memory and computation costs also depend on decoding and evaluation. ### Included contract environment @@ -487,9 +566,8 @@ labels/token kinds; arbitrary found/context/remainder trees are not expanded. bundle**. Its allowlist includes the annotation lowerer's `matchResult`, `withContract` and `err`, direct checks/Result helpers, contract combinators and the pure contract-effect helpers. Exported function trees already contain their -transitive dependencies: bindings reference existing handles, not recompiled base -source. `id`, `pair`, general base helpers, and capitalized type aliases remain -available for user definitions. Contract names are ordinary source names and must +transitive dependencies; bindings reference their existing handles. `id`, `pair`, +general base helpers, and capitalized type aliases remain available for user definitions. Contract names are ordinary source names and must be distinct from top-level definitions in this compiler profile. The checked-identity example is `id x =@nat? x`, applied to natural 42. Both argument @@ -502,36 +580,32 @@ The full binding list is in `src/contracts.ts`. Compiler and application share o heap; phase collection retains compiled handles. The independent Haskell captures cover ordinary source, annotations, failure propagation, and collection contracts. -Curated compilation environments are fixed by `environments.json`, including the -exact compiler bundle pin. Intro, conversation, microscope and RGB compile with -an empty environment. Practical demos receive a prebaked bundle of closed base -and support helpers, prepared through Haskell using the same pinned compiler as -their published programs. Its digest and exact binding names are checked before -use. No browser import resolver or host filesystem access is introduced. Scratch -programs retain the default contract environment described above. +All ten curated demos are native modules with explicit exports and manifest-pinned +imports. Standalone profiles in `environments.json` supply authenticated +compatibility/test inputs. Plain scratch programs retain the default +contract environment described above. Compiler input is limited to 16,384 Unicode scalars. Diagnostic labels are limited -to 512 scalars, and displayed definitions to 16 names of 128 scalars each. Input size alone does not bound compilation work or memory. Long compilation +to 512 scalars, and local definitions to 16 names of 128 scalars each. Input size alone does not bound compilation work or memory. Long compilation is permitted. Compilation has no application node, work, frame or elapsed-time ceiling, but still has engine/OS limits. Stop terminates the Worker. Each backend retains its lazy definition set inside its live runtime Worker. -It does not export a JS checkpoint or eagerly normalize programs to simulate one. Successful runs and recoverable result-decoding/IO errors keep that set for reuse; IO continuations/results are cancelled after each finished attempt. Fatal errors -and hard Worker termination discard it. The site never substitutes a previously -compiled or published program after a failed compilation. +and hard Worker termination discard it. Failed compilation clears the previous +program. ## Sessions and cancellation The catalogue and selected package load on arrival. Hash selection links load -the exact pinned package/export; no link grants permission to execute it. +the exact pinned package/export. Evaluate starts execution. The first source edit queues compilation; expression evaluation loads its compiler on demand. Explicitly selecting the compiler package simply loads that library. -Opening/closing Settings or scrolling to ecosystem content does not cancel work. +Work continues while using Settings or scrolling through the page. Source remains editable during compilation; active evaluation/IO locks editing until completion or Stop. Page departure, Stop or replacement terminates the -owning Worker. There are no tab-change or hidden-panel lifecycle rules. +owning Worker. Compilation and program execution have no configurable node, evaluator-frame, work or active-time ceilings. The former optional-limit editors, settings and @@ -627,7 +701,7 @@ files with atomic no-clobber links. Matching files retain inode/mtime; corrupt o symlink objects fail rather than being overwritten. No mutable aliases need registration. The pack also seeds immutable `packages/NAME/VERSION` records after their bundle objects, using the same no-clobber checks. Conflicting existing versions fail before installing missing -objects. No HTTPS upload is performed, and old objects/releases are never deleted. +objects, preserving existing objects and releases. The target filesystem must support hard links; the store and its ancestor permissions are controlled by the operator. New directories are subject to the service umask; new bundle objects are read-only/world-readable. @@ -732,7 +806,7 @@ Inspect the new compiler pin, provenance, exact release versions, environments, source hashes and goldens together. Commit the refreshed assets and tests, retain validation evidence, and complete scratch retention. The site/dependency outputs must match; do not activate a site without its corresponding registry dependencies. -These steps prepare and validate local release assets, not a public deployment. +These steps prepare and validate local release assets for deployment. ## Shared browser code and JavaScript conformance evaluator @@ -808,15 +882,65 @@ constructor batches can allocate before another reducer safe point. ## Application preparation -The practical source units use `demos/practical-support.tri`, which provides -scalar validation and record builders. Canonical-natural validation and binary -arithmetic reuse the accepted library instead of duplicating it. -`prepare.py` genuinely compiles it with selected existing `base.*` trees from the -pinned compiler bundle, then closes these handles into each demo. Demos record the -support-source digest and base names alongside actual compiler/host identities. -No runtime library fetching or additional evaluator primitives are needed. -Editing a practical demo selects its prebaked helper environment automatically. -Scratch programs instead receive only the default contract environment. +All ten demo sources in `demos/` are editable native modules. Start Here teaches +constructors, functions, application and literals without imports. Conversation +imports IO; RGB imports canonical-byte validation. Tree microscope keeps the +structural traversal visible but imports successor/Boolean operations. Business +examples import base arithmetic and, where needed, Arboricx's Unicode scalar-text +validator. Their small record literals describe the demo output schema directly. +Parser and lexer import the complete prelude/parser/lexer interfaces. + +`prepare.py` compiles the eight core sources through the authenticated shipped +native compiler, importing their exact dependency bundles into a temporary indexed +store. It checks public interfaces, independent application/IO goldens, malformed +values and nonforcing demand probes before updating assets. `prepare-index.py` +uses `practical-support.tri` to reproduce the standalone test profile. + +To refresh the parser/lexer demo releases: + +```sh +python3 ext/demo-site/prepare-showcase.py result/bin/tricu \ + --directory /tmp/arboricx-demo-refresh --demos-only \ + --version NEW_UNUSED_VERSION --stage-site +``` + +This mode still authenticates compiler inputs, dependencies, native results and +manifest identities. Source-only changes to these catalogue entries also require +an explicit new accepted release. Keep historical named versions immutable. +The browser module matrix recompiles all ten demos on both backends and compares +every result/terminal transcript with native captures, then edits and restores the +parser/lexer examples through the real page. + +### Complete library publication + +`prepare-libraries.py` publishes one complete public interface for every +`lib/**/*.tri` source under `tricu-lib-MODULE`, including compiler helpers, +experiments, and libraries requiring native host capabilities. It derives coverage +from the source tree. Fixture-backed +modules retain every authenticated public root; other library modules compile +against those exact interfaces with an explicitly pinned stable compiler. + +```sh +nix build .# +python3 ext/demo-site/prepare-libraries.py result/bin/tricu \ + --version 0.1.0 --stage-site +``` + +Omit `--stage-site` for validation without changing site assets. Reusing a version +requires identical executable and manifest identities. Changed libraries require +a fresh version; existing releases remain immutable and indexed. Preparation +checks current fixture sources, transport limits, native publication, and an +independent indexed import before staging the complete batch. Temporary stores +are removed on exit. The ordinary site dependency pack includes these releases +without additional seeder configuration. + +Each release records two distinct pins: the SHA-256 of transport bytes and the +native module-manifest identity. `module-identity.ts` reproduces native indexed +import identity without unfolding executable trees; `module-resolver.ts` checks +both identities when fetching an explicitly indexed manifest. The module tests +compare these calculations with native-published library manifests and check +full source/interface coverage and corrupt or mismatched transport rejection. +Use the published manifest pins with the native source import syntax above. ## Build / regenerate / validate @@ -827,6 +951,8 @@ No npm installation. Tooling comes from the repository's locked nixpkgs: ./ext/demo-site/build.sh --check # fresh temporary compile; exact shipped-JS parity nix shell --inputs-from . nixpkgs#nodejs -c python3 ext/demo-site/test/run-bounded.py \ --seconds 60 -- node --max-old-space-size=512 --test --test-concurrency=1 ext/demo-site/test/*.test.mjs +# Independent native CLI oracle for browser module semantics: +python3 ext/demo-site/test/native-modules.py result/bin/tricu # Actual Runtime-selector integration on the packaged site (Chromium + Firefox) nix build .#arboricxSite --no-link SITE=$(nix path-info .#arboricxSite) @@ -839,6 +965,25 @@ TEST_BACKEND=zig-wasm ARBORICX_SITE_ROOT="$SITE" nix shell --inputs-from . nixpk node ext/demo-site/test/backend-browser.mjs "$SITE/runtime/haskell" chromium TEST_BACKEND=zig-wasm ARBORICX_SITE_ROOT="$SITE" nix shell --inputs-from . nixpkgs#nodejs nixpkgs#firefox -c \ node ext/demo-site/test/backend-firefox.mjs "$SITE/runtime/haskell" firefox +# Manifest-import integration, both production backends and both engines: +for BACKEND in haskell-wasm zig-wasm; do + TEST_MODULES=1 TEST_BACKEND="$BACKEND" ARBORICX_SITE_ROOT="$SITE" \ + nix shell --inputs-from . nixpkgs#nodejs nixpkgs#chromium -c \ + node ext/demo-site/test/backend-browser.mjs "$SITE/runtime/haskell" chromium + TEST_MODULES=1 TEST_BACKEND="$BACKEND" ARBORICX_SITE_ROOT="$SITE" \ + nix shell --inputs-from . nixpkgs#nodejs nixpkgs#firefox -c \ + node ext/demo-site/test/backend-firefox.mjs "$SITE/runtime/haskell" firefox +done +# Local file/export round trip, both backends (also use backend-firefox.mjs): +for BACKEND in haskell-wasm zig-wasm; do + TEST_LOCAL_MODULES=1 TEST_BACKEND="$BACKEND" ARBORICX_SITE_ROOT="$SITE" \ + BENCHMARK_REPORT="/tmp/local-$BACKEND.json" \ + nix shell --inputs-from . nixpkgs#nodejs nixpkgs#chromium -c \ + node ext/demo-site/test/backend-browser.mjs "$SITE/runtime/haskell" chromium +done +# Native import/run + independent compilation must agree with browser exports: +python3 ext/demo-site/test/local-module-native.py result/bin/tricu \ + /tmp/local-haskell-wasm.json /tmp/local-zig-wasm.json # Heavy compiler comparisons: explicit opt-in, not included in *.test.mjs nix shell --inputs-from . nixpkgs#nodejs -c node --max-old-space-size=768 ext/demo-site/test/compiler-conformance.mjs nix shell --inputs-from . nixpkgs#nodejs -c node --max-old-space-size=768 ext/demo-site/test/contracts-conformance.mjs @@ -944,6 +1089,13 @@ from engine code caches. These figures do not measure Internet cold-download latency, mobile battery use or isolated reducer throughput. The benchmark does not alter the site's default backend or impose execution deadlines on users. +`test/native-modules.py` independently checks native CLI import/export behavior, +including header-only reexports, collisions and lexical scope. It also checks +complete canonical function-tree digests in `test/module-goldens.json`; the module +browser probe compares both runtimes against those digests, not just application +results. Intentional compiler changes require an independently reviewed native +recapture (`--capture PATH`), never expectations generated by the browser. + The bounded runner uses a Linux per-process writable-data limit, an aggregate process-group RSS watchdog and a whole-job deadline. The watchdog is sampled, not a cgroup guarantee. Run Node tests serially. Binary artifact checks compare @@ -962,8 +1114,7 @@ python3 ext/demo-site/prepare-index.py result/bin/tricu --version shipping=0.2.0 Old index entries and bundles are retained. `release.py` includes all indexed releases in the dependency pack, so both current and historical selections can be seeded before site activation. Publication metadata is separate from source -and runnable presets. These commands are administrative preparation, not public -network publication. +and runnable presets. These commands prepare release assets locally. Long full-source draft comparisons are explicitly opt-in (optional final argument selects a single demo). They use independent Haskell result captures, keep the @@ -992,17 +1143,14 @@ python3 ext/demo-site/prepare.py result/bin/tricu --backend stable python3 ext/demo-site/test/prepare-contracts.py result/bin/tricu ``` -Preparation uses the authenticated shipped compiler bundle and explicit -`source_unit.compileStableModuleDefinitions` entrypoint and fresh temporary stores. -Original demos/ordinary compiler goldens use an empty environment; contract captures -assemble the selected base bindings from independently Haskell-executed exports. Standalone demo units deliberately have no import or -export headers and do not compile working-tree library code. Selected exact -stable trees are genuinely packed via Haskell into `.arboricx` bundles. Each -selected application then executes under the Haskell host; IO uses its driver. -Bundle bytes, source hashes, compiler/host identities, and captured results are -recorded in `demos.json` and the catalogue. Preparation compiles standalone -application units with the retained compiler; compiler/library fixtures and -fingerprints stay unchanged. +Demo preparation uses the authenticated shipped native compiler and fresh indexed +stores. Native headers resolve the libraries pinned in the authored sources. The lower +`source_unit.compileStableModuleDefinitions` API still compiles isolated demand +probes against published demo exports. Contract captures assemble their selected +base bindings independently. Selected applications execute under Haskell; IO uses +its driver. Bundle/source hashes, native and unit compiler identities, host identity +and captured results are recorded in `demos.json` and the catalogue. Compiler and +library fixtures/fingerprints stay unchanged. `test/prepare-compiler.py` captures compiled applications and parser/resolver diagnostics with the Haskell host. The conformance runner checks exact compiled diff --git a/ext/demo-site/bundles/0a3956e0f6e794d843f56d734b14259c63a6e9ece22ec73d73f8f995f1578fa8.arboricx b/ext/demo-site/bundles/0a3956e0f6e794d843f56d734b14259c63a6e9ece22ec73d73f8f995f1578fa8.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/10dfca05efdf0113e65f5cb77de96b5e8d768c9e9749b05cda1e344715a44230.arboricx b/ext/demo-site/bundles/10dfca05efdf0113e65f5cb77de96b5e8d768c9e9749b05cda1e344715a44230.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/1f18232479e776982515edc3fe2c0f39fad79e2b428c2ff040d92edf5441ac6a.arboricx b/ext/demo-site/bundles/1f18232479e776982515edc3fe2c0f39fad79e2b428c2ff040d92edf5441ac6a.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/20c71797fca0c2d7c6e1a5482da8cfce80292463cba731187645e96dc17dbe2e.arboricx b/ext/demo-site/bundles/20c71797fca0c2d7c6e1a5482da8cfce80292463cba731187645e96dc17dbe2e.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/2c8f29c5e1a96eac7b6d57f6dad02f7adbfca1da93742f48c2aff3534c378284.arboricx b/ext/demo-site/bundles/2c8f29c5e1a96eac7b6d57f6dad02f7adbfca1da93742f48c2aff3534c378284.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/30715cbaf97e966bcb8ef49c9f5da1fca571308db49b103b428de713b9ad302f.arboricx b/ext/demo-site/bundles/30715cbaf97e966bcb8ef49c9f5da1fca571308db49b103b428de713b9ad302f.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/3b4474558c2336c95a122ef32c4f3070ce67b2e0491539f757594a0ac02b0c6a.arboricx b/ext/demo-site/bundles/3b4474558c2336c95a122ef32c4f3070ce67b2e0491539f757594a0ac02b0c6a.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/3de401378f33dd8f93e9ca11c1c2bd73a458dabcd8d631a33ba17306f83d7d3b.arboricx b/ext/demo-site/bundles/3de401378f33dd8f93e9ca11c1c2bd73a458dabcd8d631a33ba17306f83d7d3b.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/3e32ef46cd9a7032469c6b004917c9b8982da95673d486a576fc31541bbe51c6.arboricx b/ext/demo-site/bundles/3e32ef46cd9a7032469c6b004917c9b8982da95673d486a576fc31541bbe51c6.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/40dfb23da91b505ea4586bbfea46a7374d299bb747796f18428de7da43fa7315.arboricx b/ext/demo-site/bundles/40dfb23da91b505ea4586bbfea46a7374d299bb747796f18428de7da43fa7315.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5.arboricx b/ext/demo-site/bundles/493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea.arboricx b/ext/demo-site/bundles/4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/5188bb1a7ede262cb63f02daadff9b827c05bd26ace2e7f23528e9dd10ba6121.arboricx b/ext/demo-site/bundles/5188bb1a7ede262cb63f02daadff9b827c05bd26ace2e7f23528e9dd10ba6121.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/51d352cb5306a96b0275e6cf80c5a7d160e7379cf8f31aa128d96fe3e56043ff.arboricx b/ext/demo-site/bundles/51d352cb5306a96b0275e6cf80c5a7d160e7379cf8f31aa128d96fe3e56043ff.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5.arboricx b/ext/demo-site/bundles/64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a.arboricx b/ext/demo-site/bundles/679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/718c96fe7ab33504ece9c041f7a93dddf15b281f8dfceba84291a349e260b15f.arboricx b/ext/demo-site/bundles/718c96fe7ab33504ece9c041f7a93dddf15b281f8dfceba84291a349e260b15f.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3.arboricx b/ext/demo-site/bundles/730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/7b7b8b132f1192bf4a9e379b641382167f9be38a609bdad18b144dfa85da2b3c.arboricx b/ext/demo-site/bundles/7b7b8b132f1192bf4a9e379b641382167f9be38a609bdad18b144dfa85da2b3c.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/7fbcf00a8412785c5c61b61c21c89d00d2597953b040faa02e6e811677b37578.arboricx b/ext/demo-site/bundles/7fbcf00a8412785c5c61b61c21c89d00d2597953b040faa02e6e811677b37578.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/84a7479abac8663864a5615e5c0be69b6bb64530a904ab0da274bbf68b682b01.arboricx b/ext/demo-site/bundles/84a7479abac8663864a5615e5c0be69b6bb64530a904ab0da274bbf68b682b01.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/8675a2bc53b5820d45cce64c072c55f7e03d23b1b4960a45f952fc6387023024.arboricx b/ext/demo-site/bundles/8675a2bc53b5820d45cce64c072c55f7e03d23b1b4960a45f952fc6387023024.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb.arboricx b/ext/demo-site/bundles/8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/a51d9fcffd12aebc39166e2ba4e5b86896832db299f06322b7a2805bc4d57f05.arboricx b/ext/demo-site/bundles/a51d9fcffd12aebc39166e2ba4e5b86896832db299f06322b7a2805bc4d57f05.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/a8d7805b268f93ef72e10c7031bc709fb9924ca91b2eacdd313f70d96d254560.arboricx b/ext/demo-site/bundles/a8d7805b268f93ef72e10c7031bc709fb9924ca91b2eacdd313f70d96d254560.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/aabb749e392a47605ffd08f12ec442747641d190ca2c4240f3196744f6fdbd22.arboricx b/ext/demo-site/bundles/aabb749e392a47605ffd08f12ec442747641d190ca2c4240f3196744f6fdbd22.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/acb79eb9c2f56a18c1c740aaaee97e9e5e53f55b56602bd16a351d85cfadc192.arboricx b/ext/demo-site/bundles/acb79eb9c2f56a18c1c740aaaee97e9e5e53f55b56602bd16a351d85cfadc192.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/af2b3483281c7c4e24151956dce5d763dfe4deeb4b0ec7635a341b443b2b4584.arboricx b/ext/demo-site/bundles/af2b3483281c7c4e24151956dce5d763dfe4deeb4b0ec7635a341b443b2b4584.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/af66062931c5de826bd336625d53c1c354fe6cc736e56e247ae550c542f0fa8a.arboricx b/ext/demo-site/bundles/af66062931c5de826bd336625d53c1c354fe6cc736e56e247ae550c542f0fa8a.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/b61e8d7d31f730c1e4db08c729435302e76eb911ee2c45b110f2932a60b2eb33.arboricx b/ext/demo-site/bundles/b61e8d7d31f730c1e4db08c729435302e76eb911ee2c45b110f2932a60b2eb33.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/b82891447d90b9c9bfeef4c8a75d15589ef008d9142e32f8694bd0ce083fb8ca.arboricx b/ext/demo-site/bundles/b82891447d90b9c9bfeef4c8a75d15589ef008d9142e32f8694bd0ce083fb8ca.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368.arboricx b/ext/demo-site/bundles/b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/bd742a4ec55cf68f1f1b382979fdf6b5c098039089be16c76b4621b8ca07d9cb.arboricx b/ext/demo-site/bundles/bd742a4ec55cf68f1f1b382979fdf6b5c098039089be16c76b4621b8ca07d9cb.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/c0a9ffd923b4dd17f6c1fd105502d9e82a9064f75b6312b37c155c94a3ce73d3.arboricx b/ext/demo-site/bundles/c0a9ffd923b4dd17f6c1fd105502d9e82a9064f75b6312b37c155c94a3ce73d3.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/d2842a47b4f76d3d0bf86914620a33b5251319167c74873e7f630923f4b95e68.arboricx b/ext/demo-site/bundles/d2842a47b4f76d3d0bf86914620a33b5251319167c74873e7f630923f4b95e68.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/d7105ef477224dfb10ad2773e54744cb3f87ddf304eb753d7cb9ba40ea9cc3df.arboricx b/ext/demo-site/bundles/d7105ef477224dfb10ad2773e54744cb3f87ddf304eb753d7cb9ba40ea9cc3df.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/decfff4079c7c202f664a55496926cce1fcd1e9c67cf67b84718bf7d663e6f4d.arboricx b/ext/demo-site/bundles/decfff4079c7c202f664a55496926cce1fcd1e9c67cf67b84718bf7d663e6f4d.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/e8f5fbfbb768926c5dcc43511fed05a2436f0bf46f2a18c75408496886cb1539.arboricx b/ext/demo-site/bundles/e8f5fbfbb768926c5dcc43511fed05a2436f0bf46f2a18c75408496886cb1539.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/eac98c45250ba80f2331cb71128306b25bd61b4e8e3e063b9b635ec654f4d698.arboricx b/ext/demo-site/bundles/eac98c45250ba80f2331cb71128306b25bd61b4e8e3e063b9b635ec654f4d698.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/ed931d1cf10921f414c7fb2e21c4ab40509d548b56ca1db1327586d90cdf6f0a.arboricx b/ext/demo-site/bundles/ed931d1cf10921f414c7fb2e21c4ab40509d548b56ca1db1327586d90cdf6f0a.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/f13735828b62a6d90e95b2964e5fdf72d4e5181aa49d48c04cf134b5606bc10e.arboricx b/ext/demo-site/bundles/f13735828b62a6d90e95b2964e5fdf72d4e5181aa49d48c04cf134b5606bc10e.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/faea17b7579cd7193af19cb74a34266cdf8ac2d9934a24d8552dd09edd5cb4c5.arboricx b/ext/demo-site/bundles/faea17b7579cd7193af19cb74a34266cdf8ac2d9934a24d8552dd09edd5cb4c5.arboricx Binary files differ. diff --git a/ext/demo-site/bundles/fc37dd8c558961c88211c3f4faf31bc438bcda12384f94125f563f1651e09ac9.arboricx b/ext/demo-site/bundles/fc37dd8c558961c88211c3f4faf31bc438bcda12384f94125f563f1651e09ac9.arboricx Binary files differ. diff --git a/ext/demo-site/catalogue.json b/ext/demo-site/catalogue.json @@ -2,9 +2,9 @@ { "id": "intro", "title": "Start here", - "hash": "6d46e48b8aa41bde5d086804c4ee8e2ed4d355ce9c4b302f20cc709cbfd4d2e0", - "source": "-- Start here: a small tricu language guide.\n-- Lines beginning with -- are comments. Read down, then try the exports.\n-- Choose an export in the right panel; its suggested inputs load for you.\n\n-- 1. Definitions give a name to a value: name = expression.\n-- Every value is a tree. These are the three constructor forms.\nleaf = t\nstem = t t\nfork = t t t\n-- Select leaf, stem or fork with Tree graph to see its structure.\n\n-- 2. A lambda names an input before the colon and returns an expression.\nidentity = (x : x)\n-- Select identity: try a string argument, then a number with Natural number.\n\n-- 3. Named parameters are a convenient way to write functions.\n-- This is equivalent to first = (a b : a).\nfirst a b = a\n-- Select first: it returns the first of its two arguments.\n\n-- 4. Application is written with spaces and groups to the left.\n-- first 7 9 means (first 7) 9. Parentheses group an expression explicitly.\nanswer = identity (first 42 7)\n-- Select answer with [] arguments and Natural number: the result is 42.\n-- [] in the arguments box means this definition needs no further inputs.\n\n-- 5. Numbers, quoted strings and lists are convenient tree literals.\ngreeting = \"Hello from tricu!\"\nnumbers = [1 2 3]\n-- Select greeting with Text, or numbers with List to inspect its elements.\n-- In source, list items use spaces; the playground's input box uses JSON.\n\n-- 6. The result interpretation tells the playground how to read a tree.\n-- Use Text for a string, Natural number for a number, Tree graph for any tree.\n-- Pure value observes the result; Browser IO interprets an IO action tree.\n-- The Conversation demo shows input, output and continuations.\n\n-- To change this program, copy it into Compiler, edit it and compile locally.\n-- Then run a definition repeatedly with different arguments.\n-- For an application spanning lines, put the entire call in parentheses.\n-- Workspace programs can import libraries with !import module as NS.\n-- Next: Tree microscope shows how functions can inspect other program trees.\n", - "sourceSha256": "d560aa46055d3206cf96747e2d13e00a8499833dc6a9a8453a26a0c608a52b15", + "hash": "64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5", + "source": "!export *\n\n-- Start here: a small tricu language guide.\n-- Lines beginning with -- are comments. Read down, then try the exports.\n-- Edit this source in place; valid edits compile after a short pause.\n-- Write a call in Evaluate tricu expression, then press Evaluate.\n-- Imports/exports declare a module; this introductory one needs no libraries.\n\n-- 1. Definitions give a name to a value: name = expression.\n-- Every value is a tree. These are the three constructor forms.\nleaf = t\nstem = t t\nfork = t t t\n-- Evaluate leaf, stem or fork with tricu · t source to see its structure.\n\n-- 2. A lambda names an input before the colon and returns an expression.\nidentity = (x : x)\n-- Try identity \"Hello!\" with Text, then identity 42 with Natural number.\n\n-- 3. Named parameters are a convenient way to write functions.\n-- This is equivalent to first = (a b : a).\nfirst a b = a\n-- Try first 7 9: it returns the first of its two arguments.\n\n-- 4. Application is written with spaces and groups to the left.\n-- first 7 9 means (first 7) 9. Parentheses group an expression explicitly.\nanswer = identity (first 42 7)\n-- Evaluate answer with Natural number: the result is 42.\n-- A name by itself needs no further arguments; [] is an empty-list value.\n\n-- 5. Numbers, quoted strings and lists are convenient tree literals.\ngreeting = \"Hello from tricu!\"\nnumbers = [1 2 3]\n-- Evaluate greeting with Text, or numbers with Bytes to display [1, 2, 3].\n-- Bytes requires a list of naturals in 0..255; use t source for other lists.\n-- Lists use spaces, not commas: try identity [4 5 6].\n\n-- 6. The result interpretation tells the playground how to read a tree.\n-- Use Text for a string, Natural number for a number, or t source for any tree.\n-- Pure value observes the result; Browser IO interprets an IO action tree.\n-- The Conversation demo shows input, output and continuations.\n\n-- Settings also offers structured arguments and stored-definition inspection.\n-- Edits stay local; Restore original returns to the published source.\n-- For an application spanning lines, put the entire call in parentheses.\n-- Other demos import libraries by immutable manifest hash, shown in their headers.\n-- Next: Tree microscope shows how functions can inspect other program trees.\n", + "sourceSha256": "24835a93f2da82d4b16876074e18634045e750e832a6694bd6067ba78e1a5508", "export": "answer", "arguments": [], "output": "number", @@ -46,22 +46,22 @@ }, "numbers": { "arguments": [], - "output": "list", + "output": "bytes", "mode": "pure" }, "leaf": { "arguments": [], - "output": "tree", + "output": "tricu", "mode": "pure" }, "stem": { "arguments": [], - "output": "tree", + "output": "tricu", "mode": "pure" }, "fork": { "arguments": [], - "output": "tree", + "output": "tricu", "mode": "pure" } }, @@ -71,8 +71,8 @@ "id": "greet", "title": "A conversation", "hash": "0811457d501113ee11194f90e279ebb4ef9d548c70cb48d146be03eb9af7505f", - "source": "-- Standalone browser demo: constructors match lib/io.tri version 1.\nio action = t \"tricuIO\" (t 1 action)\npure value = t 0 value\nbind action k = t 1 (t action k)\nputStr text = t 10 text\ngetLine = t 11 t\n\nmain = (io (do bind\n putStr \"What is your name?\\n\"\n name <- getLine\n putStr \"Hello, \"\n putStr name\n putStr \"!\\n\"\n pure name))\n", - "sourceSha256": "8cd92eb18ed9152d7ea3fed8e82ec2b2fb92551277eefb4f3f020c8998321538", + "source": "!import 2d23be85d277457fd36c84f5eaa227e94e1c4efec281ff73017aaee109096f49 as IO\n!export main\n\n-- A conversation built from the IO library's actions and explicit bind operator.\n-- Evaluate main in Browser IO mode, then answer in the terminal input.\n-- The returned name is also displayed as Text. Try changing the greeting.\n-- Importing IO does not grant filesystem or network access in the browser.\nmain = (IO.io (do IO.bind\n IO.putStr \"What is your name?\\n\"\n name <- IO.getLine\n IO.putStr \"Hello, \"\n IO.putStr name\n IO.putStr \"!\\n\"\n IO.pure name))\n", + "sourceSha256": "3b9835aec1f3b987ad954cd235a7c0517170d3f7e236b15d60ce9a3a809c74c4", "export": "main", "arguments": [], "output": "string", @@ -83,9 +83,9 @@ { "id": "microscope", "title": "Tree microscope", - "hash": "a1919c931e13a4b29536e09b3230a7cda3e972934cdfb401aa50ceffbdba70ef", - "source": "-- Structural operations on data OR program trees. No source evaluation.\n-- Direct three-constructor dispatch is intentional: ordered-pattern workers\n-- cost 3.9x the aggregate work on the retained 16-case screen. No lazy* thunks.\ntriage leaf stem fork = t (t leaf stem) fork\ntrue = t t\nfalse = t\nboth a b = triage false (ignored : b) (ignored ignored2 : b) a\n\nshape tree = triage \"Leaf\" (child : \"Stem\") (left right : \"Fork\") tree\n\n-- Canonical numbers are least-significant-bit lists, not unary numbers.\nsucc n = (triage 1 (ignored : 0)\n (bit rest : triage (t (t t) rest) (ignored : t t (succ rest)) (ignored ignored2 : 0) bit)\n n)\n\ncount tree acc = (triage\n (succ acc)\n (child : count child (succ acc))\n (left right : count right (count left (succ acc)))\n tree)\n\nsize tree = count tree 0\n\nsame a b = (triage\n (triage true (ignored : false) (ignored ignored2 : false) b)\n (x : triage false (y : same x y) (ignored ignored2 : false) b)\n (x y : triage false (ignored : false) (u v : both (same x u) (same y v)) b)\n a)\n", - "sourceSha256": "40716bc35732ffca8ad2862c025a3280dec2b5a9b469c9485a20bf6e1569a4c2", + "hash": "493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 as B\n!export shape\n!export size\n!export same\n\n-- Inspect data OR compiled program trees, not source text.\n-- Try shape (t t t), size (t t t), or same (t t) (t t).\n-- Also try shape (x : x): functions are inspectable trees too.\n-- triage dispatches directly on Leaf, Stem and Fork without visiting children.\n-- Arithmetic and Booleans come from base; traversal is the subject of this demo.\nshape tree = B.triage \"Leaf\" (child : \"Stem\") (left right : \"Fork\") tree\n\n-- Count every constructor occurrence, including repeated shared branches.\n-- This is expanded tree size, not allocated nodes or source-code length.\ncount tree acc = (B.triage\n (B.succ acc)\n (child : count child (B.succ acc))\n (left right : count right (count left (B.succ acc)))\n tree)\n\nsize tree = count tree 0\n\nsame a b = (B.triage\n (B.triage B.true (ignored : B.false) (ignored ignored2 : B.false) b)\n (x : B.triage B.false (y : same x y) (ignored ignored2 : B.false) b)\n (x y : B.triage B.false (ignored : B.false) (u v : B.and? (same x u) (same y v)) b)\n a)\n", + "sourceSha256": "0dd0bb5444662200cf3556dd7a81e65570b5d3b34d4b3e6b17e6d9c36d3d1114", "export": "size", "arguments": [ { @@ -136,9 +136,9 @@ { "id": "rgb", "title": "RGB validator", - "hash": "a90ff53f2e05424ad536d7b819fb1710dab83127f0516d66384bd9bbe8ddbda2", - "source": "-- Exactly three canonical bytes: reject redundant high zero bits too.\ntrue = t t\nfalse = t\nboth left right = triage false (_ : right) (_ _ : right) left\n\n-- Direct constructor dispatch in this per-bit hot loop avoids repeated pattern\n-- tests. A nonzero numeral's final bit must be true, not a redundant high zero.\ntriage leaf stem fork = t (t leaf stem) fork\nbit? value = triage true (child : triage true (_ : false) (_ _ : false) child) (_ _ : false) value\nbits? number budget = (triage true (_ : false)\n (bit rest : triage false (_ : false)\n (_ remaining : both (bit? bit)\n (triage bit (_ : false) (_ _ : bits? rest remaining) rest))\n budget)\n number)\nbyte? value = bits? value [t t t t t t t t]\n\nmain (t _) = \"Expected a list.\"\nmain [_ | (t _)] = \"Expected a list.\"\nmain [_ | [_ | (t _)]] = \"Expected a list.\"\nmain [r g b] = case both (byte? r) (both (byte? g) (byte? b)) of\n ^true = \"RGB triple accepted.\"\n _ = \"A channel is not a canonical byte (0-255).\"\nmain _ = \"Expected exactly three channels.\"\n", - "sourceSha256": "3eec1b9e51ae69a5655e8cd1b79d20fd8f478a6491cc4cdfb4eee63df1b9e254", + "hash": "b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 7a24af56a9ce9b947cadcafd3a9da127b1507275bfac62b9fa55e27490b176dc as Binary\n!export main\n\n-- Validate an RGB list using the library's canonical-byte predicate.\n-- Try main [64 128 255], main [0 256 255], or main [0 1].\n-- Canonical encoding matters: redundant high zero bits are rejected too.\n-- List-shape errors are separate from invalid channels; checks short-circuit.\nmain (t _) = \"Expected a list.\"\nmain [_ | (t _)] = \"Expected a list.\"\nmain [_ | [_ | (t _)]] = \"Expected a list.\"\nmain [r g b] = case and? (Binary.binaryByte? r) (and? (Binary.binaryByte? g) (Binary.binaryByte? b)) of\n ^true = \"RGB triple accepted.\"\n _ = \"A channel is not a canonical byte (0-255).\"\nmain _ = \"Expected exactly three channels.\"\n", + "sourceSha256": "33da7deb793df280f59b47913b57562dbb2820525f19451ba5e4042219ef559e", "export": "main", "arguments": [ { @@ -158,9 +158,9 @@ { "id": "shipping", "title": "Shipping policies", - "hash": "efbdff446802ddcfe353461dce3ea75b60187fce601f0f47cfe7320511aea02e", - "source": "-- Shipping policy: arguments are destination, cart subtotal in cents, grams.\n-- Destinations: domestic, regional, international. Grams: 1..5000.\n-- Select v1/v2 with the same cart: domestic free shipping changes from $75 to $100.\n-- Otherwise domestic costs $4.99/$5.99, regional $9.99, international $19.99.\n-- Packages above 1kg add $2.50. Subtotals are bounded to $10,000.\n-- The bundle hash + export pins the policy used to reproduce a quote later.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nbaseRate 1 \"domestic\" = 499\nbaseRate _ \"domestic\" = 599\nbaseRate _ \"regional\" = 999\nbaseRate _ _ = 1999\n\npaidRate version zone grams = case lessEq grams 1000 of\n ^true = baseRate version zone\n _ = addBinary 250 (baseRate version zone)\n\nfreeThreshold 1 = 7500\nfreeThreshold _ = 10000\n\namount version zone subtotal grams = case and? (equal? zone \"domestic\") (lessEq (freeThreshold version) subtotal) of\n ^true = 0\n _ = paidRate version zone grams\n\nquote version zone subtotal grams = case and? (natural? subtotal) (natural? grams) of\n ^true = (case or? (equal? zone \"domestic\") (or? (equal? zone \"regional\") (equal? zone \"international\")) of\n ^true = (case and? (lessEq subtotal 1000000) (and? (lessEq 1 grams) (lessEq grams 5000)) of\n ^true = [(stringField \"status\" \"ok\") (numberField \"policyVersion\" version)\n (stringField \"destination\" zone) (numberField \"shippingCents\" (amount version zone subtotal grams))]\n _ = failure \"Subtotal must be <=1000000 cents; grams must be 1..5000.\")\n _ = failure \"Unknown destination.\")\n _ = failure \"Subtotal and grams must be canonical natural numbers.\"\n\nv1 zone subtotal grams = quote 1 zone subtotal grams\nv2 zone subtotal grams = quote 2 zone subtotal grams\n", - "sourceSha256": "6738b22bab5fe1a349404eefa0368cb4e492d6b7a6b0cf679ab4a146ee8b0aa2", + "hash": "4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!export v1\n!export v2\n\n-- Shipping policy: arguments are destination, cart subtotal in cents, grams.\n-- Destinations: domestic, regional, international. Grams: 1..5000.\n-- Select v1/v2 with the same cart: domestic free shipping changes from $75 to $100.\n-- Otherwise domestic costs $4.99/$5.99, regional $9.99, international $19.99.\n-- Packages above 1kg add $2.50. Subtotals are bounded to $10,000.\n-- The bundle hash + export pins the policy used to reproduce a quote later.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies canonical-natural checks, arithmetic and Booleans.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nbaseRate 1 \"domestic\" = 499\nbaseRate _ \"domestic\" = 599\nbaseRate _ \"regional\" = 999\nbaseRate _ _ = 1999\n\npaidRate version zone grams = case lte_? grams 1000 of\n ^true = baseRate version zone\n _ = add 250 (baseRate version zone)\n\nfreeThreshold 1 = 7500\nfreeThreshold _ = 10000\n\namount version zone subtotal grams = case and? (equal? zone \"domestic\") (lte_? (freeThreshold version) subtotal) of\n ^true = 0\n _ = paidRate version zone grams\n\nquote version zone subtotal grams = case and? (isNat? subtotal) (isNat? grams) of\n ^true = (case or? (equal? zone \"domestic\") (or? (equal? zone \"regional\") (equal? zone \"international\")) of\n ^true = (case and? (lte_? subtotal 1000000) (and? (lte_? 1 grams) (lte_? grams 5000)) of\n ^true = [[\"status\" 0 \"ok\"] [\"policyVersion\" 1 version]\n [\"destination\" 0 zone] [\"shippingCents\" 1 (amount version zone subtotal grams)]]\n _ = failure \"Subtotal must be <=1000000 cents; grams must be 1..5000.\")\n _ = failure \"Unknown destination.\")\n _ = failure \"Subtotal and grams must be canonical natural numbers.\"\n\nv1 zone subtotal grams = quote 1 zone subtotal grams\nv2 zone subtotal grams = quote 2 zone subtotal grams\n", + "sourceSha256": "d6d9378ab39733a8aabaf4f6a25851350e99fa81607bf05a64266301e2712f5a", "export": "v1", "arguments": [ { @@ -216,14 +216,14 @@ "mode": "pure" } }, - "environment": "practical" + "environment": "empty" }, { "id": "events", "title": "Event adapters", - "hash": "0844067dd63e9e6fc252a2ab2343b1937bb31abd8e44ad6683895f81d0c2499c", - "source": "-- Event adapter: two producers, one consumer-facing record schema.\n-- vendorA accepts [eventName customer totalCents]. eventName is purchase/refund.\n-- vendorB accepts [customer refunded totalCents]. refunded is a Boolean.\n-- Both return schemaVersion, eventType, customer and amountCents.\n-- Try the two exports: their presets describe the same order.created event.\n-- A producer can publish the adapter hash alongside its event schema.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nnormalized event customer cents = case text? customer of\n ^true = (case and? (natural? cents) (lessEq cents 1000000) of\n ^true = [(numberField \"schemaVersion\" 1) (stringField \"eventType\" event)\n (stringField \"customer\" customer) (numberField \"amountCents\" cents)]\n _ = failure \"amountCents must be a canonical natural <=1000000.\")\n _ = failure \"customer must be scalar text.\"\n\nfromA \"purchase\" customer cents = normalized \"order.created\" customer cents\nfromA \"refund\" customer cents = normalized \"order.refunded\" customer cents\nfromA _ _ _ = failure \"Unknown vendor A event.\"\n\nfromB customer ^true cents = normalized \"order.refunded\" customer cents\nfromB customer ^false cents = normalized \"order.created\" customer cents\nfromB _ _ _ = failure \"refunded must be a canonical Boolean.\"\n\n-- Preserve list-shape diagnostics without inspecting any field before dispatch.\nunpack handler (t _) = failure \"Expected a list.\"\nunpack handler [_ | (t _)] = failure \"Expected a list.\"\nunpack handler [_ | [_ | (t _)]] = failure \"Expected a list.\"\nunpack handler [a b c] = handler a b c\nunpack _ _ = failure \"Expected exactly three fields.\"\n\nvendorA values = unpack fromA values\nvendorB values = unpack fromB values\n", - "sourceSha256": "c0a6deee9945ae50a71c68461030af7cdbce30495bb6d154b98e393bb70280a1", + "hash": "8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export vendorA\n!export vendorB\n\n-- Event adapter: two producers, one consumer-facing record schema.\n-- vendorA accepts [eventName customer totalCents]. eventName is purchase/refund.\n-- vendorB accepts [customer refunded totalCents]. refunded is a Boolean.\n-- Both return schemaVersion, eventType, customer and amountCents.\n-- Try the two exports: their presets describe the same order.created event.\n-- A producer can publish the adapter hash alongside its event schema.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nnormalized event customer cents = case A.hostString? customer of\n ^true = (case and? (isNat? cents) (lte_? cents 1000000) of\n ^true = [[\"schemaVersion\" 1 1] [\"eventType\" 0 event]\n [\"customer\" 0 customer] [\"amountCents\" 1 cents]]\n _ = failure \"amountCents must be a canonical natural <=1000000.\")\n _ = failure \"customer must be scalar text.\"\n\nfromA \"purchase\" customer cents = normalized \"order.created\" customer cents\nfromA \"refund\" customer cents = normalized \"order.refunded\" customer cents\nfromA _ _ _ = failure \"Unknown vendor A event.\"\n\nfromB customer ^true cents = normalized \"order.refunded\" customer cents\nfromB customer ^false cents = normalized \"order.created\" customer cents\nfromB _ _ _ = failure \"refunded must be a canonical Boolean.\"\n\n-- Preserve list-shape diagnostics without inspecting any field before dispatch.\nunpack handler (t _) = failure \"Expected a list.\"\nunpack handler [_ | (t _)] = failure \"Expected a list.\"\nunpack handler [_ | [_ | (t _)]] = failure \"Expected a list.\"\nunpack handler [a b c] = handler a b c\nunpack _ _ = failure \"Expected exactly three fields.\"\n\nvendorA values = unpack fromA values\nvendorB values = unpack fromB values\n", + "sourceSha256": "ca11d9a7e20bfe228545c43f50aed57089c020eead516e23b67d909fae8923de", "export": "vendorA", "arguments": [ { @@ -294,14 +294,14 @@ "mode": "pure" } }, - "environment": "practical" + "environment": "empty" }, { "id": "registration", "title": "Registration validator", - "hash": "a8ea6cb0c1d175206448456e907790f5204f43c48581f588ddb4894d4c40b996", - "source": "-- Registration validator: name, email, age, termsAccepted are separate arguments.\n-- Returns one field-specific message per input, plus an accepted Boolean.\n-- Name must be nonempty scalar text. Age must be a natural from 18 to 120.\n-- Email uses a deliberately small rule: nonempty text containing @ and a dot.\n-- Terms must be the canonical true Boolean. This is a teaching policy, not SMTP validation.\n-- Browser and server can pin this same executable instead of duplicating rules.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nnameMessage name = case text? name of\n ^true = (case name of\n [] = \"Name is required.\"\n _ = \"\")\n _ = \"Name must be scalar text.\"\n\nemailMessage email = case text? email of\n ^true = (case and? (contains? \"@\" email) (contains? \".\" email) of\n ^true = \"\"\n _ = \"Email must contain @ and a dot.\")\n _ = \"Email must be scalar text.\"\n\nageMessage age = case natural? age of\n ^true = (case and? (lessEq 18 age) (lessEq age 120) of\n ^true = \"\"\n _ = \"Age must be from 18 to 120.\")\n _ = \"Age must be a canonical natural.\"\n\ntermsMessage ^true = \"\"\ntermsMessage _ = \"Accept the terms.\"\n\nreport name email age terms = [\n (boolField \"accepted\" (and? (equal? name \"\") (and? (equal? email \"\") (and? (equal? age \"\") (equal? terms \"\")))))\n (stringField \"nameError\" name) (stringField \"emailError\" email)\n (stringField \"ageError\" age) (stringField \"termsError\" terms)]\n\nmain name email age terms = report (nameMessage name) (emailMessage email) (ageMessage age) (termsMessage terms)\n", - "sourceSha256": "bc01d7b3af0dabb3c467aa06e48d7c18118276bc087dda0ea867f8a1a660ef05", + "hash": "679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export main\n\n-- Registration validator: name, email, age, termsAccepted are separate arguments.\n-- Returns one field-specific message per input, plus an accepted Boolean.\n-- Name must be nonempty scalar text. Age must be a natural from 18 to 120.\n-- Email uses a deliberately small rule: nonempty text containing @ and a dot.\n-- Terms must be the canonical true Boolean. This is a teaching policy, not SMTP validation.\n-- Browser and server can pin this same executable instead of duplicating rules.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nnameMessage name = case A.hostString? name of\n ^true = (case name of\n [] = \"Name is required.\"\n _ = \"\")\n _ = \"Name must be scalar text.\"\n\nemailMessage email = case A.hostString? email of\n ^true = (case and? (contains? \"@\" email) (contains? \".\" email) of\n ^true = \"\"\n _ = \"Email must contain @ and a dot.\")\n _ = \"Email must be scalar text.\"\n\nageMessage age = case isNat? age of\n ^true = (case and? (lte_? 18 age) (lte_? age 120) of\n ^true = \"\"\n _ = \"Age must be from 18 to 120.\")\n _ = \"Age must be a canonical natural.\"\n\ntermsMessage ^true = \"\"\ntermsMessage _ = \"Accept the terms.\"\n\nreport name email age terms = [\n [\"accepted\" 2 (and? (equal? name \"\") (and? (equal? email \"\") (and? (equal? age \"\") (equal? terms \"\"))))]\n [\"nameError\" 0 name] [\"emailError\" 0 email]\n [\"ageError\" 0 age] [\"termsError\" 0 terms]]\n\nmain name email age terms = report (nameMessage name) (emailMessage email) (ageMessage age) (termsMessage terms)\n", + "sourceSha256": "531866c6b2e7e42ecbd4ae285c502b59321ad31fd2b82b36d8a139938592ac31", "export": "main", "arguments": [ { @@ -347,14 +347,14 @@ "mode": "pure" } }, - "environment": "practical" + "environment": "empty" }, { "id": "migration", "title": "Profile migrations", - "hash": "41f27e53f2cde13130dc5a9c3e74de49d16f94f7dc565ca4357c55ce4ba5280d", - "source": "-- Archived profile v0: [name email]. v1: adds schemaVersion and displayName.\n-- v2: also supplies marketingOptIn=false; existing data is preserved.\n-- Select v1/v2 with the same input to compare the two target schemas.\n-- A migration receipt can record the input identity, executable hash/export,\n-- output identity and wire schema. Running this demo stays entirely local.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nmigrate version name email = case and? (text? name) (text? email) of\n ^true = (case version of\n 1 = [(numberField \"schemaVersion\" 1) (stringField \"displayName\" name) (stringField \"email\" email)]\n _ = [(numberField \"schemaVersion\" 2) (stringField \"displayName\" name) (stringField \"email\" email)\n (boolField \"marketingOptIn\" false)])\n _ = failure \"Name and email must be scalar text.\"\n\nprofile _ (t _) = failure \"Expected a list.\"\nprofile _ [_ | (t _)] = failure \"Expected a list.\"\nprofile version [name email] = migrate version name email\nprofile _ _ = failure \"Expected [name email].\"\n\nv1 values = profile 1 values\nv2 values = profile 2 values\n", - "sourceSha256": "3f8b8125203b08e6e57b83f509b445e08c882da6fe507efe338bfde0649f3f8a", + "hash": "730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export v1\n!export v2\n\n-- Archived profile v0: [name email]. v1: adds schemaVersion and displayName.\n-- v2: also supplies marketingOptIn=false; existing data is preserved.\n-- Select v1/v2 with the same input to compare the two target schemas.\n-- A migration receipt can record the input identity, executable hash/export,\n-- output identity and wire schema. Running this demo stays entirely local.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nmigrate version name email = case and? (A.hostString? name) (A.hostString? email) of\n ^true = (case version of\n 1 = [[\"schemaVersion\" 1 1] [\"displayName\" 0 name] [\"email\" 0 email]]\n _ = [[\"schemaVersion\" 1 2] [\"displayName\" 0 name] [\"email\" 0 email]\n [\"marketingOptIn\" 2 false]])\n _ = failure \"Name and email must be scalar text.\"\n\nprofile _ (t _) = failure \"Expected a list.\"\nprofile _ [_ | (t _)] = failure \"Expected a list.\"\nprofile version [name email] = migrate version name email\nprofile _ _ = failure \"Expected [name email].\"\n\nv1 values = profile 1 values\nv2 values = profile 2 values\n", + "sourceSha256": "66ee7bc1a9005b5f1d12f168b7866231ad7f523cf34f52b63958cb155a5c49b5", "export": "v1", "arguments": [ { @@ -413,15 +413,16 @@ "mode": "pure" } }, - "environment": "practical" + "environment": "empty" }, { "id": "parser", "preparation": "native", + "environment": "empty", "title": "Parser combinators", "hash": "355e41506f39e05da8c8a72a68aa810a486e062480322bac11af67e86980520e", - "source": "!import prelude *\n!import parser *\n!import native_math as N\n!export parseNames\n!export parsePrefix\n\n-- Lowercase names separated by commas. Try \"red,green\", \"red,,blue\",\n-- \"red,\" and \"red green\". A comma commits to another name.\n-- parseNames requires the entire input; parsePrefix exposes any remainder.\n-- These native imports are pinned at preparation time. Source is read-only\n-- here because browser draft compilation does not resolve native modules.\nnameParser = parserLabel \"lowercase name\" (parserSome (parserSatisfy (c : N.inRange c 97 122)))\ncommaParser = parserThen (parserExpect 44) parserCommit\nnamesPrefix = parserSepBy1 nameParser commaParser\nnamesComplete = parserBefore namesPrefix (parserLabel \"end of input\" parserEof)\n\nreport reply = (parserMatchReply\n (diagnostic rest consumed committed : [\n [\"status\" 0 \"error\"]\n [\"expected\" 0 (parserDiagnosticExpected diagnostic)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n (names rest consumed committed : [\n [\"status\" 0 \"ok\"]\n [\"names\" 0 (intercalate \", \" names)]\n [\"count\" 1 (length names)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n reply)\nparseNames text = report (namesComplete text)\nparsePrefix text = report (namesPrefix text)\n", - "sourceSha256": "3405e18774db8de759b7793880e1568c156d68e5fe4a388e09b95ff301d896f5", + "source": "!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 *\n!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d *\n!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N\n!export parseNames\n!export parsePrefix\n\n-- Lowercase names separated by commas. Try \"red,green\", \"red,,blue\",\n-- \"red,\" and \"red green\". A comma commits to another name.\n-- parseNames requires the entire input; parsePrefix exposes any remainder.\n-- Edit the parser or labels below; valid edits compile locally.\n-- Imports pin complete library interfaces, fetched only when compiling.\nnameParser = parserLabel \"lowercase name\" (parserSome (parserSatisfy (c : N.inRange c 97 122)))\ncommaParser = parserThen (parserExpect 44) parserCommit\nnamesPrefix = parserSepBy1 nameParser commaParser\nnamesComplete = parserBefore namesPrefix (parserLabel \"end of input\" parserEof)\n\nreport reply = (parserMatchReply\n (diagnostic rest consumed committed : [\n [\"status\" 0 \"error\"]\n [\"expected\" 0 (parserDiagnosticExpected diagnostic)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n (names rest consumed committed : [\n [\"status\" 0 \"ok\"]\n [\"names\" 0 (intercalate \", \" names)]\n [\"count\" 1 (length names)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n reply)\nparseNames text = report (namesComplete text)\nparsePrefix text = report (namesPrefix text)\n", + "sourceSha256": "18aa0a464dabb595749abdab5edb1bb11c4356c0e753cf0985a644901bb5c241", "export": "parseNames", "arguments": [ { @@ -457,10 +458,11 @@ { "id": "lexer", "preparation": "native", + "environment": "empty", "title": "Located lexer scans", "hash": "e756a481b3056a2e76f50316ccf77bfab8b15727b7bec899580c2eb919e668b2", - "source": "!import prelude *\n!import parser *\n!import lexer *\n!import native_math as N\n!export scanWord\n!export scanWhitespace\n\n-- Positioned prefix scans, not whole-input parsers. The remainder begins\n-- at the first nonmatching character. Positions count source characters,\n-- not UTF-8 bytes or display columns: only LF advances the line.\n-- Native imports are pinned during preparation; browser source is read-only.\nreport reply = (let\n payload = parserReplyPayload reply\n end = snd payload\n in [\n [\"matched\" 0 (fst payload)]\n [\"remaining\" 0 (parserReplyRest reply)]\n [\"line\" 1 (lexerPositionLine end)]\n [\"column\" 1 (lexerPositionColumn end)]\n [\"offset\" 1 (lexerPositionOffset end)]\n [\"consumed\" 2 (parserReplyConsumed reply)]])\n\nscan predicate text = report (lexerMapScan reverse\n (lexerScanWhile text lexerStart [] predicate (state character : pair character state)))\nscanWord text = scan (character : N.inRange character 97 122) text\nscanWhitespace text = scan (character : or? (equal? character 32)\n (or? (equal? character 9) (equal? character 10))) text\n", - "sourceSha256": "5478169b100e087b8f8862418a2cd5d0e593edcc299a122b762842483f4525e0", + "source": "!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 *\n!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d *\n!import 816df1a32853750a1254112aff8ae8c55ca86bf70e809d226969ab1d43a6688b *\n!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N\n!export scanWord\n!export scanWhitespace\n\n-- Positioned prefix scans, not whole-input parsers. The remainder begins\n-- at the first nonmatching character. Positions count source characters,\n-- not UTF-8 bytes or display columns: only LF advances the line.\n-- Edit a predicate below and evaluate scanWord \"hello,world\" to compare.\n-- scanWhitespace accepts space, LF and tab, but deliberately not CR.\nreport reply = (let\n payload = parserReplyPayload reply\n end = snd payload\n in [\n [\"matched\" 0 (fst payload)]\n [\"remaining\" 0 (parserReplyRest reply)]\n [\"line\" 1 (lexerPositionLine end)]\n [\"column\" 1 (lexerPositionColumn end)]\n [\"offset\" 1 (lexerPositionOffset end)]\n [\"consumed\" 2 (parserReplyConsumed reply)]])\n\nscan predicate text = report (lexerMapScan reverse\n (lexerScanWhile text lexerStart [] predicate (state character : pair character state)))\nscanWord text = scan (character : N.inRange character 97 122) text\nscanWhitespace text = scan (character : or? (equal? character 32)\n (or? (equal? character 9) (equal? character 10))) text\n", + "sourceSha256": "ec68af4102c16ef56be01e78a3288bea57af71ca57ab35374a0d12005b5a10a1", "export": "scanWord", "arguments": [ { diff --git a/ext/demo-site/demos.json b/ext/demo-site/demos.json @@ -1,16 +1,17 @@ { "schema": 1, "backend": "stable", + "nativeCompilerSha256": "d70de875988dfa309f2c167992928866f88b08af351918b8c7b5d88c541c6e94", "compilerExport": "source_unit.compileStableModuleDefinitions", "compilerBundleSha256": "9c61d59cd76036000691da6ff5e2e9f641cf5c614b424d7280e052cfcb716e75", "compilerManifest": "17df7d4ef56684d423ca59d5f4c4d03aa73b24c5579e00f8719e2f06641c39e6", - "hostSha256": "662fcf80231c070e4aa15dff1438aa1f5c99fb27a905f46a62efaff46c49f668", + "hostSha256": "c1eea492839b4425f285dd3a0765bbb8bdc323d2320a2181760d34180ee15073", "demos": { "intro": { "demandCases": [], - "source": "-- Start here: a small tricu language guide.\n-- Lines beginning with -- are comments. Read down, then try the exports.\n-- Choose an export in the right panel; its suggested inputs load for you.\n\n-- 1. Definitions give a name to a value: name = expression.\n-- Every value is a tree. These are the three constructor forms.\nleaf = t\nstem = t t\nfork = t t t\n-- Select leaf, stem or fork with Tree graph to see its structure.\n\n-- 2. A lambda names an input before the colon and returns an expression.\nidentity = (x : x)\n-- Select identity: try a string argument, then a number with Natural number.\n\n-- 3. Named parameters are a convenient way to write functions.\n-- This is equivalent to first = (a b : a).\nfirst a b = a\n-- Select first: it returns the first of its two arguments.\n\n-- 4. Application is written with spaces and groups to the left.\n-- first 7 9 means (first 7) 9. Parentheses group an expression explicitly.\nanswer = identity (first 42 7)\n-- Select answer with [] arguments and Natural number: the result is 42.\n-- [] in the arguments box means this definition needs no further inputs.\n\n-- 5. Numbers, quoted strings and lists are convenient tree literals.\ngreeting = \"Hello from tricu!\"\nnumbers = [1 2 3]\n-- Select greeting with Text, or numbers with List to inspect its elements.\n-- In source, list items use spaces; the playground's input box uses JSON.\n\n-- 6. The result interpretation tells the playground how to read a tree.\n-- Use Text for a string, Natural number for a number, Tree graph for any tree.\n-- Pure value observes the result; Browser IO interprets an IO action tree.\n-- The Conversation demo shows input, output and continuations.\n\n-- To change this program, copy it into Compiler, edit it and compile locally.\n-- Then run a definition repeatedly with different arguments.\n-- For an application spanning lines, put the entire call in parentheses.\n-- Workspace programs can import libraries with !import module as NS.\n-- Next: Tree microscope shows how functions can inspect other program trees.\n", - "sourceSha256": "d560aa46055d3206cf96747e2d13e00a8499833dc6a9a8453a26a0c608a52b15", - "hash": "6d46e48b8aa41bde5d086804c4ee8e2ed4d355ce9c4b302f20cc709cbfd4d2e0", + "source": "!export *\n\n-- Start here: a small tricu language guide.\n-- Lines beginning with -- are comments. Read down, then try the exports.\n-- Edit this source in place; valid edits compile after a short pause.\n-- Write a call in Evaluate tricu expression, then press Evaluate.\n-- Imports/exports declare a module; this introductory one needs no libraries.\n\n-- 1. Definitions give a name to a value: name = expression.\n-- Every value is a tree. These are the three constructor forms.\nleaf = t\nstem = t t\nfork = t t t\n-- Evaluate leaf, stem or fork with tricu · t source to see its structure.\n\n-- 2. A lambda names an input before the colon and returns an expression.\nidentity = (x : x)\n-- Try identity \"Hello!\" with Text, then identity 42 with Natural number.\n\n-- 3. Named parameters are a convenient way to write functions.\n-- This is equivalent to first = (a b : a).\nfirst a b = a\n-- Try first 7 9: it returns the first of its two arguments.\n\n-- 4. Application is written with spaces and groups to the left.\n-- first 7 9 means (first 7) 9. Parentheses group an expression explicitly.\nanswer = identity (first 42 7)\n-- Evaluate answer with Natural number: the result is 42.\n-- A name by itself needs no further arguments; [] is an empty-list value.\n\n-- 5. Numbers, quoted strings and lists are convenient tree literals.\ngreeting = \"Hello from tricu!\"\nnumbers = [1 2 3]\n-- Evaluate greeting with Text, or numbers with Bytes to display [1, 2, 3].\n-- Bytes requires a list of naturals in 0..255; use t source for other lists.\n-- Lists use spaces, not commas: try identity [4 5 6].\n\n-- 6. The result interpretation tells the playground how to read a tree.\n-- Use Text for a string, Natural number for a number, or t source for any tree.\n-- Pure value observes the result; Browser IO interprets an IO action tree.\n-- The Conversation demo shows input, output and continuations.\n\n-- Settings also offers structured arguments and stored-definition inspection.\n-- Edits stay local; Restore original returns to the published source.\n-- For an application spanning lines, put the entire call in parentheses.\n-- Other demos import libraries by immutable manifest hash, shown in their headers.\n-- Next: Tree microscope shows how functions can inspect other program trees.\n", + "sourceSha256": "24835a93f2da82d4b16876074e18634045e750e832a6694bd6067ba78e1a5508", + "hash": "64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5", "mode": "pure", "haskellCases": [ { @@ -114,8 +115,8 @@ }, "greet": { "demandCases": [], - "source": "-- Standalone browser demo: constructors match lib/io.tri version 1.\nio action = t \"tricuIO\" (t 1 action)\npure value = t 0 value\nbind action k = t 1 (t action k)\nputStr text = t 10 text\ngetLine = t 11 t\n\nmain = (io (do bind\n putStr \"What is your name?\\n\"\n name <- getLine\n putStr \"Hello, \"\n putStr name\n putStr \"!\\n\"\n pure name))\n", - "sourceSha256": "8cd92eb18ed9152d7ea3fed8e82ec2b2fb92551277eefb4f3f020c8998321538", + "source": "!import 2d23be85d277457fd36c84f5eaa227e94e1c4efec281ff73017aaee109096f49 as IO\n!export main\n\n-- A conversation built from the IO library's actions and explicit bind operator.\n-- Evaluate main in Browser IO mode, then answer in the terminal input.\n-- The returned name is also displayed as Text. Try changing the greeting.\n-- Importing IO does not grant filesystem or network access in the browser.\nmain = (IO.io (do IO.bind\n IO.putStr \"What is your name?\\n\"\n name <- IO.getLine\n IO.putStr \"Hello, \"\n IO.putStr name\n IO.putStr \"!\\n\"\n IO.pure name))\n", + "sourceSha256": "3b9835aec1f3b987ad954cd235a7c0517170d3f7e236b15d60ce9a3a809c74c4", "hash": "0811457d501113ee11194f90e279ebb4ef9d548c70cb48d146be03eb9af7505f", "mode": "io", "haskellCases": [ @@ -158,9 +159,9 @@ "result": "22021021020202021002210210210210202102100220210202021021021002210210202102021021000" } ], - "source": "-- Structural operations on data OR program trees. No source evaluation.\n-- Direct three-constructor dispatch is intentional: ordered-pattern workers\n-- cost 3.9x the aggregate work on the retained 16-case screen. No lazy* thunks.\ntriage leaf stem fork = t (t leaf stem) fork\ntrue = t t\nfalse = t\nboth a b = triage false (ignored : b) (ignored ignored2 : b) a\n\nshape tree = triage \"Leaf\" (child : \"Stem\") (left right : \"Fork\") tree\n\n-- Canonical numbers are least-significant-bit lists, not unary numbers.\nsucc n = (triage 1 (ignored : 0)\n (bit rest : triage (t (t t) rest) (ignored : t t (succ rest)) (ignored ignored2 : 0) bit)\n n)\n\ncount tree acc = (triage\n (succ acc)\n (child : count child (succ acc))\n (left right : count right (count left (succ acc)))\n tree)\n\nsize tree = count tree 0\n\nsame a b = (triage\n (triage true (ignored : false) (ignored ignored2 : false) b)\n (x : triage false (y : same x y) (ignored ignored2 : false) b)\n (x y : triage false (ignored : false) (u v : both (same x u) (same y v)) b)\n a)\n", - "sourceSha256": "40716bc35732ffca8ad2862c025a3280dec2b5a9b469c9485a20bf6e1569a4c2", - "hash": "a1919c931e13a4b29536e09b3230a7cda3e972934cdfb401aa50ceffbdba70ef", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 as B\n!export shape\n!export size\n!export same\n\n-- Inspect data OR compiled program trees, not source text.\n-- Try shape (t t t), size (t t t), or same (t t) (t t).\n-- Also try shape (x : x): functions are inspectable trees too.\n-- triage dispatches directly on Leaf, Stem and Fork without visiting children.\n-- Arithmetic and Booleans come from base; traversal is the subject of this demo.\nshape tree = B.triage \"Leaf\" (child : \"Stem\") (left right : \"Fork\") tree\n\n-- Count every constructor occurrence, including repeated shared branches.\n-- This is expanded tree size, not allocated nodes or source-code length.\ncount tree acc = (B.triage\n (B.succ acc)\n (child : count child (B.succ acc))\n (left right : count right (count left (B.succ acc)))\n tree)\n\nsize tree = count tree 0\n\nsame a b = (B.triage\n (B.triage B.true (ignored : B.false) (ignored ignored2 : B.false) b)\n (x : B.triage B.false (y : same x y) (ignored ignored2 : B.false) b)\n (x y : B.triage B.false (ignored : B.false) (u v : B.and? (same x u) (same y v)) b)\n a)\n", + "sourceSha256": "0dd0bb5444662200cf3556dd7a81e65570b5d3b34d4b3e6b17e6d9c36d3d1114", + "hash": "493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5", "mode": "pure", "haskellCases": [ { @@ -322,13 +323,13 @@ { "label": "invalid-first-byte", "source": "q x = x x\nprobe ignored = main [(t t) (q q) (q q)]", - "program": "2120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102021020202102100220202021021021021002210202020202102100221021020202021021002202021020210210210022020210210202102100221020202102102102100220202020202100220202102021021021002202020210202102100220210202021021021002210202102020210210022102021020202102100220202020202100221021020202021021002202020210202102100221020202020210210022021021021020210210022021021021020210210022102021020202102100220202102102021021002210210202021021021002202102102102021000202022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100020212011212011212121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200202022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021212002120021201021100202002120102110021201121200212002120102120112121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002121200212002120102110020200212010212120021200212120021200212120021200212011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120102121200212002120102110020200202020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212010212120021200212010211002020020211002120102110021201120102121200212002120112002120112002120112010212120021200212010212002120021201121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002121200212002120102110020200212120021200212011200212011200212011201120021201120112002120112120021200212010212002120021212002120021201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212010212120021200212010211002020021201021212002120021201021100202002120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021212002120021201021200212002120112002120112002120112011200212011201120021201120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112011201021201120112011202121201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202022021020202102021002210210210202020210022021020202020210022020202020210022020210202102102100220210202021021021002210202021020210210022020202021021021002202021021020210210022102021020202102100220202020202100221020202020210210022102102020202102100221021020202021021002210202102020210210022020202021021021002202021020210210210022102021020202102100220202102020210210022021021021020210002121200212002120102110020200212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020221020202020202100220202020202100221021020202021021002202020210202102100221020202020210210022021021021020210210022021021021020210210022102021020202102100220202102102021021002202020202021002210202021020210210022102102020210210210022020202020210022021021021020210210022102102102102021021002202021020210210210022020202020210022102020202021021002202020202021002210210202020210210022102020202021021002202102102102021021002210210210210202102100220210210210202102100221020202102021021002210210202020210210022102020202021021002202021021020210210022020202020210022021020202021021002210202021021021021002202021020210210210022102021020202102100220202020202100220202021020210022020202021021002210202102102021002202102020210210022102021020210210022102021020210210022102020210202100220210210210202100021212002120021201021200212002120102120021200212011202120112121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201021100212010212010211002120102110021201120212120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002120112011201021201121200212002120102120021200212011202120112121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201021100212010212010211002120102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200211002020200211002120102110021212002120021201120021201120021201120112002120112011200212011212002120021201021200212002121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202020021201021201120112010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020212010211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110020202020202020202002120102110020212120021200212010212002120021201120212011212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120102110021201021201021100212010211002120112021212021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212011201120102120112120021200212010212002120021201120212011212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120102110021201021201021100212010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021100202020021100212010211002121200212002120112002120112002120112011200212011201120021201121200212002120102120021200212120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020202002120102120112011201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202021201021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002020202020202020200212010211002021201120212120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002120112011201021201121200212002120102120021200212011202120112121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201021100212010212010211002120102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200211002020200211002120102110021212002120021201120021201120021201120112002120112011200212011212002120021201021200212002121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202020021201021201120112010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020212010211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110020202020202020202002120102110020212010212010212010212120021200212010211002020020212010212010212010212010212120021200212010211002020020202020211002020202110020212010211002020202022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022102102020202102100220202021020210210022102020202021021002202102102102021021002202102102102021021002210202102020210210022020210210202102100221021020202102102100220210210210202100021100212011021212002120212110021100202121100211002121200212021211002110020212110021100200", + "program": "212021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022102102020202102100220202021020210210022102020202021021002202102102102021021002202102102102021021002210202102020210210022020210210202102100221021020202102102100220210210210202100020202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020202020210210022020202020210022020210210202102100221020202102021021002210210202021021021002202021020210210210022021021021020210002021201121201121212120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212120021200212010211002020020202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020202020210210022020202020210022020210210202102100221020202102021021002210210202021021021002202021020210210210022021021021020210002120102121200212002120102110020200212010211002120112120021200212010212011212121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200212120021200212010211002020021201021212002120021212002120021212002120021201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212010212120021200212010211002020020202022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021201021212002120021201021100202002021100212010211002120112010212120021200212011200212011200212011201021212002120021201021200212002120112121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200212120021200212010211002020021212002120021201120021201120021201120112002120112011200212011212002120021201021200212002121200212002120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201021212002120021201021100202002120102121200212002120102110020200212011201120102121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002121200212002120102120021200212011200212011200212011201120021201120112002120112011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201120102120112011201120212120112121202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110020202202102020210202100221021021020202021002202102020202021002202020202021002202021020210210210022021020202102102100221020202102021021002202020202102102100220202102102021021002210202102020210210022020202020210022102020202021021002210210202020210210022102102020202102100221020210202021021002202020202102102100220202102021021021002210202102020210210022020210202021021002202102102102021000212120021200212010211002020021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202022102020202020210022020202020210022102102020202102100220202021020210210022102020202021021002202102102102021021002202102102102021021002210202102020210210022020210210202102100220202020202100221020202102021021002210210202021021021002202020202021002202102102102021021002210210210210202102100220202102021021021002202020202021002210202020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102020202102100221020202102102102100220202102021021021002210202102020210210022020202020210022020202102021002202020202102100221020210210202100220210202021021002210202102021021002210202102021021002210202021020210022021021021020210002121200212002120102120021200212010212002120021201120222002021100202021100212011202121202220020211002020211002120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110021212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100211002021021021021021021021021002120102110020212120021200212010212002120021201120222002021100202021100212011202121202220020211002020211002120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110021212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100211002021021021021021021021021002120102110020212011202121202220020211002020211002120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110021212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100211002021021021021021021021021002120102110020212010212010212010212120021200212010211002020020212010212010212010212010212120021200212010211002020020202020211002020202110020212010211002020202022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022102102020202102100220202021020210210022102020202021021002202102102102021021002202102102102021021002210202102020210210022020210210202102100221021020202102102100220210210210202100021100212011021212002120212110021100202121100211002121200212021211002110020212110021100200", "result": "2210202020202021002202020202021002210210202020210210022020202102021021002210202020202102100220210210210202102100220210210210202102100221020210202021021002202021021020210210022020202020210022102020210202102100221021020202102102100220202020202100220210210210202102100221021021021020210210022020210202102102100220202020202100221020202020210210022020202020210022102102020202102100221020202020210210022021021021020210210022102102102102021021002202102102102021021002210202021020210210022102102020202102100221020202020210210022020210210202102100220202020202100220210202020210210022102020210210210210022020210202102102100221020210202021021002202020202021002202020210202100220202020210210022102021021020210022021020202102100221020210202102100221020210202102100221020202102021002202102102102021000" } ], - "source": "-- Exactly three canonical bytes: reject redundant high zero bits too.\ntrue = t t\nfalse = t\nboth left right = triage false (_ : right) (_ _ : right) left\n\n-- Direct constructor dispatch in this per-bit hot loop avoids repeated pattern\n-- tests. A nonzero numeral's final bit must be true, not a redundant high zero.\ntriage leaf stem fork = t (t leaf stem) fork\nbit? value = triage true (child : triage true (_ : false) (_ _ : false) child) (_ _ : false) value\nbits? number budget = (triage true (_ : false)\n (bit rest : triage false (_ : false)\n (_ remaining : both (bit? bit)\n (triage bit (_ : false) (_ _ : bits? rest remaining) rest))\n budget)\n number)\nbyte? value = bits? value [t t t t t t t t]\n\nmain (t _) = \"Expected a list.\"\nmain [_ | (t _)] = \"Expected a list.\"\nmain [_ | [_ | (t _)]] = \"Expected a list.\"\nmain [r g b] = case both (byte? r) (both (byte? g) (byte? b)) of\n ^true = \"RGB triple accepted.\"\n _ = \"A channel is not a canonical byte (0-255).\"\nmain _ = \"Expected exactly three channels.\"\n", - "sourceSha256": "3eec1b9e51ae69a5655e8cd1b79d20fd8f478a6491cc4cdfb4eee63df1b9e254", - "hash": "a90ff53f2e05424ad536d7b819fb1710dab83127f0516d66384bd9bbe8ddbda2", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 7a24af56a9ce9b947cadcafd3a9da127b1507275bfac62b9fa55e27490b176dc as Binary\n!export main\n\n-- Validate an RGB list using the library's canonical-byte predicate.\n-- Try main [64 128 255], main [0 256 255], or main [0 1].\n-- Canonical encoding matters: redundant high zero bits are rejected too.\n-- List-shape errors are separate from invalid channels; checks short-circuit.\nmain (t _) = \"Expected a list.\"\nmain [_ | (t _)] = \"Expected a list.\"\nmain [_ | [_ | (t _)]] = \"Expected a list.\"\nmain [r g b] = case and? (Binary.binaryByte? r) (and? (Binary.binaryByte? g) (Binary.binaryByte? b)) of\n ^true = \"RGB triple accepted.\"\n _ = \"A channel is not a canonical byte (0-255).\"\nmain _ = \"Expected exactly three channels.\"\n", + "sourceSha256": "33da7deb793df280f59b47913b57562dbb2820525f19451ba5e4042219ef559e", + "hash": "b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368", "mode": "pure", "haskellCases": [ { @@ -410,13 +411,13 @@ { "label": "invalid-subtotal", "source": "q x = x x\nprobe ignored = v1 (q q) (t t) (q q)", - "program": "2121212021212002120021201120021201120021212002120021201021200212002120112120212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120102120112011201120021201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201021201120112011200212011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112010212011201120112002120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201120102120112011201120112120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210210210210202102100221021020210202102100021212002120021201021200212002120102120021200212010212002120021201120021201121202121200212002120102120021100202120121002121200211002002022020202021021021002210210210210202102100220202102102021021002210202021020210210022102102020202102100221020202102102102100220210210202102021002210202102020210210022021020202102102100221021020202102102100221020202102021021002210210210210202102100220210210210202102100021201021100212011212002120021201021200212002120102120021200212011200212011212021212002120021201021200211002021201021212002110020020220202102020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022021021021020210210022102020202021021002202021020210210210022102020210202102100221021021021020210210022021021021020210210002120102110021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120021201120112011201121202121200212002120102120021100202120121002121200211002002022102102020210210210022020202102021021002210202021020210210022020202021021021002202020202102102100221020202102021021002202102102102021021002210210210202021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021201120021201120112011212011212120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002020021212002120021201021100202002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201021201120112010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201120212120021200212011212002120021212002120021201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112120021200212011212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202021021020202102102102102100212010212120021200212010211002020021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022020210202021021002210210210210202102100221020210210202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100221021020202021021000202121200212002120102110020200212010212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020210020212120021200212010212011212120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002020210210210202102021020202100212120021200212010211002020021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022020210202021021002210210210210202102100221020210210202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100221021020202021021000212010212120021200212010212011212120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002020210210210202021021021021021002121200212002120102110020200212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220210202021021021002210202102020210210022102102102020210210022102020210202102100221021021021020210210022021021021020210210022102020202021021002202021021020210210002020202102102102102020210210210210210021201021100202120102110020202121200212002120102110020200202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010212011201021201120112120212121202121200212002120112002120112002120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201021212002120021201120021201120021201120112002120112011200212011201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112011201021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201121200212002120112002120112002120112011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002020212010212010211002020202110020202110020212010212120021200212011202120112010212120021200212010212002110020211002120102110020200202120102121200212002120112120212120021200212011200212011200212011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120102121200212002120112002120112002120112011200212011201120021201120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201120102121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112120021200212011200212011200212011201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202021201021201021100202020211002020211002021212002120021201120212011201021212002120021201021200211002021100212010211002020021201021201120112121202121200212002120112002120112002120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201021212002120021201120021201120021201120112002120112011200212011201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112011201021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201121200212002120112002120112002120112011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002020212010212010211002020202110020202110020212120021200212011202120112010212120021200212010212002110020211002120102110020200202120102110021201120112120212120021200212120021200212011202020212121202121200212002120112002120112002120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201021212002120021201120021201120021201120112002120112011200212011201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112011201021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201121200212002120112002120112002120112011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002020212010212010211002020202110020202110020212120021200212011202120112010212120021200212010212002110020211002120102110020211002021212002120021201120212011201102121200212002120102120021100202110021201021100202110021100212010211002021100212120021200212120021200212010211002021100202002021212002120021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201121202121200212002120112021201120102121200212002120102120021100202110021201021100202110020220210210210202102100221021021021020210210022020210202102102100220202020202100221020202020210210022020202020210022021021021020210210022102020202021021002202021020210210210022102021020210210210022021020202102102100221020202020210210022020210210202102100220202020202100220210210210202102100221020210202102102100221020210210202102100220210202020210210022102021020202102100220210202021021021000212010211002120112010212120021200212010212002120021201120212120021200212011202120112011021212002120021201021200211002021100212010211002021100212010211002021201021100212011201021201120102121200212002120102120021200212011202121200212002120112021201120110212120021200212010212002110020211002120102110020211002120102110020212010211002020211002120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002121200212002120102120021200212011202121200212002121200212002120112021212021211002110020212021212002120021201120021201120021201120112002120112011200212011201121200212002121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021212002120021201120212120021200212011200212011200212120021200212011200212011200212120021200212010212002120021201120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212010211002021201021100202021100202020021201021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202100202002120102121200212002120102120021200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201102110021201120112010212120021200212010212002120021201021100202120102110020202020020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212010212010211002021100202020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011200212011201120112002120112120021200212011200212011200212011201021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002121200212002120112021212002120021201120021201120021212002120021201120021201120021212002120021201021200212002120112021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021201021100202120102110020202110020202002120102120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020210020200212010212120021200212010212002120021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120110211002120112011201021212002120021201021200212002120102110020212010211002020202002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021201021201021100202120102110020202020021201021201121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120021201121200212002120112002120112002120112011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002110021100212010211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002110021100212010211002120102110020212010211002120102120102120102110021212002120021201021200212002120102120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201120102120112120021200212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201021100212010211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002110020021201021100212010211002021201021100212011201121202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002110020021201021100211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002110021100212010211002120102110020212010211002120102110020212010211002120102120102120102110020202120102120102120102110020212010212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100202002120102110020212010211002021212021212002120021212002120021201120202021212120212120021200212011200212011200212011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120102121200212002120112002120112002120112011200212011201120021201120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201120102121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112120021200212011200212011200212011201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202021201021201021100202020211002020211002021212002120021201120212011201021212002120021201021200211002021100212010211002021100202121200212002120112021201120110212120021200212010212002110020211002120102110020211002110021201021100202110021212002120021212002120021201021100202110020200202121200212002121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120112120212120021200212011202120112010212120021200212010212002110020211002120102110020211002022021021021020210210022102102102102021021002202021020210210210022020202020210022102020202021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022021021021020210210022102021020210210210022102021021020210210022021020202021021002210202102020210210022021020202102102100021201021100212011201021212002120021201021200212002120112021212002120021201120212011201102121200212002120102120021100202110021201021100202110021201021100202120102110021201120102120112010212120021200212010212002120021201120212120021200212011202120112011021212002120021201021200211002021100212010211002021100212010211002021201021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100211002121202121200212002121200212002120112020202121212021212002120021201120021201120021201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112010212120021200212011200212011200212011201120021201120112002120112011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120112010212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011212002120021201120021201120021201120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020202120102120102110020202021100202021100202121200212002120112021201120102121200212002120102120021100202110021201021100202110020212120021200212011202120112011021212002120021201021200211002021100212010211002021100211002120102110020211002121200212002121200212002120102110020211002020020212120021200212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212011212021212002120021201120212011201021212002120021201021200211002021100212010211002021100202202102102102021021002210210210210202102100220202102021021021002202020202021002210202020202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202102021021021002210202102102021021002202102020202102100221020210202021021002202102020210210210002120102110021201120102121200212002120102120021200212011202121200212002120112021201120110212120021200212010212002110020211002120102110020211002120102110020212010211002120112010212011201021212002120021201021200212002120112021212002120021201120212011201102121200212002120102120021100202110021201021100202110021201021100202120102110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021100202021020210210210210210021212002120021201021200212002120112021212002120021201121200212002121200212002120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011212002120021201121202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110020202102102020210210210210210021201021212002120021201021100202002120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202021020202102100221021021021020210210022102021021020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022102102020202102100020212120021200212010211002020021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202021002021212002120021201021201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202021021021020210202102020210021212002120021201021100202002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202021020202102100221021021021020210210022102021021020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022102102020202102100021201021212002120021201021201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202021021021020202102102102102100212120021200212010211002020021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022021020202102102100221020210202021021002210210210202021021002210202021020210210022102102102102021021002202102102102021021002210202020202102100220202102102021021000202020210210210210202021021021021021002120102110020212010211002020212120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002110020202020210202102102102102100212010211002021201021100202021201021100212011212002120021201021200212002120112022200202110020202110021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022020210202021021002210210210210202102100221020210210202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100221021020202021021000212010212120021200212010212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120112021212011212120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002020202021021020202102021020210210210021212002120021201021100202002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202100202020202020210202020210210210202021002120102110020212010211002120102110020212010211002020212010211002020202120102110020202020200202020202121200212002120102110020200202020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102102020210202100221020210202102102100220210202020210210022020210202102102100221021021021020210210022020210202102102100221020202020210210022020210210202102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202020202021002210210202020210210022102021020202102100220210210210202102100220202102021021021002210210202021021021002210210202102102100220202020202100221021021020202102100220210202021021021002210202020202102100221020210210202102100221021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210202020210210022021021021020210022021021021020210022102021020210210022020202021021002202020202102100220202020210210022021021021020210002020212120021200212010212002120021201120222002021100202021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020212120021200212011202220020211002020211002120112120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002021002120102110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202020202102020202102102102020210020202020212120021200212010211002020020202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202102021020210022021021021020210210022102102021020210210022021021021020210210022102102102102021021002210210210202102102100220210210210202102100220202020202100220202102020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022021021021020210210022102020202021021002202021020210210210022102020210202102100221021021021020210210022021021021020210210022021021021020210002021201021201021212002120021201120212011212120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110020102121212021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002010200211002120102110021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022020210202021021002210210210210202102100221020210210202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100221021020202021021000212120021200212011202120112121202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100201021212120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110020102002110021201021100212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220210202021021021002210202102020210210022102102102020210210022102020210202102100221021021021020210210022021021021020210210022102020202021021002202021021020210210002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202210202021020210210022021021021020210210022020210202102102100221020210202021021002202102020210210210022021021021020210210022102020202021021002202021020210210210022102020210202102100221021021021020210210022021021021020210210022102020202021021002202021021020210210002020202021212002120021201021100202002020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221021020202102021002210202102021021021002202102020202102100220202102021021021002210210210210202102100220202102021021021002210202020202102100220202102102021021002202020202021002210202020202102100220210210210202102100220202102020210210022020202020210022102102102020210210022021020202102102100221020202020210210022102021021020210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022021021021020210210022102021020210210210022102021021020210210022021020202021021002210202102020210210022021020202102102100221021020202102102100220210210210202100020202121200212002120112022200202110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002021002120102110020212010211002020211002120212110021100202121100211002010212021211002110020212110021100", + "program": "2121212021212002120021201120021201120021212002120021201021200212002120112120212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120102120112011201120021201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201021201120112011200212011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112010212011201120112002120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201120102120112011201120112012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221021021021020210210022102102021020210210000212120021200212010212002120021201021200212002120102120021200212010212002120122020202021021021002210210210210202102100220202102102021021002210202021020210210022102102020202102100221020202102102102100220210210202102021002210202102020210210022021020202102102100221021020202102102100221020202102021021002210210210210202102100220210210210202102100021201210021212002110020021201121200212002120102120021200212010212002120021201021200212012202021020202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100220210210210202102100221020202020210210022020210202102102100221020202102021021002210210210210202102100220210210210202102100021201021212002110020021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120021201120112011201120122102102020210210210022020202102021021002210202021020210210022020202021021021002202020202102102100221020202102021021002202102102102021021002210210210202021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210002120112011201120112012100212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011200212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002120112002120112011201121201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202002121200212002120102110020200212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102120112011201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201021212002120021201021200212002120112021212002120021201121200212002121200212002120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011212002120021201121202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110020202102102020210210210210210021201021212002120021201021100202002120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202021020202102100221021021021020210210022102021021020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022102102020202102100020212120021200212010211002020021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202021002021212002120021201021201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202021021021020210202102020210021212002120021201021100202002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202021020202102100221021021021020210210022102021021020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022102102020202102100021201021212002120021201021201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202021021021020202102102102102100212120021200212010211002020021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022021020202102102100221020210202021021002210210210202021021002210202021020210210022102102102102021021002202102102102021021002210202020202102100220202102102021021000202020210210210210202021021021021021002120102110020212010211002020212120021200212010211002020020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201021201120102120112011212021212120212120021200212011200212011200212011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120102121200212002120112002120112002120112011200212011201120021201120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201120102121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112120021200212011200212011200212011201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202021201021201021100202020211002020211002021201021212002120021201120212011201021212002120021201021200211002021100212010211002020020212010212120021200212011212021212002120021201120021201120021201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112010212120021200212011200212011200212011201120021201120112002120112011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120112010212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011212002120021201120021201120021201120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020202120102120102110020202021100202021100202121200212002120112021201120102121200212002120102120021100202110021201021100202002120102120112011212120212120021200212011200212011200212011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120102121200212002120112002120112002120112011200212011201120021201120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201120102121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112120021200212011200212011200212011201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202021201021201021100202020211002020211002021212002120021201120212011201021212002120021201021200211002021100212010211002020020212010211002120112011212021212002120021212002120021201120202021212120212120021200212011200212011200212011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120102121200212002120112002120112002120112011200212011201120021201120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201120102121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112120021200212011200212011200212011201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202021201021201021100202020211002020211002021212002120021201120212011201021212002120021201021200211002021100212010211002021100202121200212002120112021201120110212120021200212010212002110020211002120102110020211002110021201021100202110021212002120021212002120021201021100202110020200202121200212002121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120112120212120021200212011202120112010212120021200212010212002110020211002120102110020211002022021021021020210210022102102102102021021002202021020210210210022020202020210022102020202021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022021021021020210210022102021020210210210022102021021020210210022021020202021021002210202102020210210022021020202102102100021201021100212011201021212002120021201021200212002120112021212002120021201120212011201102121200212002120102120021100202110021201021100202110021201021100202120102110021201120102120112010212120021200212010212002120021201120212120021200212011202120112011021212002120021201021200211002021100212010211002021100212010211002021201021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212120021200212010212002120021201120212120021200212120021200212011202121202121100211002021202121200212002120112002120112002120112011200212011201120021201120112120021200212120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002121200212002120112021212002120021201120021201120021212002120021201120021201120021212002120021201021200212002120112021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021201021100202120102110020202110020202002120102120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020210020200212010212120021200212010212002120021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120110211002120112011201021212002120021201021200212002120102110020212010211002020202002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021201021201021100202110020202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120021201120112011200212011212002120021201120021201120021201120102120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212120021200212011202121200212002120112002120112002121200212002120112002120112002121200212002120102120021200212011202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002120102110020212010211002020211002020200212010212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002021002020021201021212002120021201021200212002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212011021100212011201120102121200212002120102120021200212010211002021201021100202020200202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002120102120102110020212010211002020202002120102120112120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112002120112120021200212011200212011200212011201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100211002110021201021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100211002110021201021100212010211002021201021100212010212010212010211002121200212002120102120021200212010212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120112010212011212002120021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102110021201021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100211002002120102110021201021100202120102110021201120112120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100211002002120102110021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100211002110021201021100212010211002021201021100212010211002021201021100212010212010212010211002020212010212010212010211002021201021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110020200212010211002021201021100202121202121200212002121200212002120112020202121212021212002120021201120021201120021201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112010212120021200212011200212011200212011201120021201120112002120112011201120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002002110021201120112010212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011212002120021201120021201120021201120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020202120102120102110020202021100202021100202121200212002120112021201120102121200212002120102120021100202110021201021100202110020212120021200212011202120112011021212002120021201021200211002021100212010211002021100211002120102110020211002121200212002121200212002120102110020211002020020212120021200212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212011212021212002120021201120212011201021212002120021201021200211002021100212010211002021100202202102102102021021002210210210210202102100220202102021021021002202020202021002210202020202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202102021021021002210202102102021021002202102020202102100221020210202021021002202102020210210210002120102110021201120102121200212002120102120021200212011202121200212002120112021201120110212120021200212010212002110020211002120102110020211002120102110020212010211002120112010212011201021212002120021201021200212002120112021212002120021201120212011201102121200212002120102120021100202110021201021100202110021201021100202120102110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021100212120212120021200212120021200212011202020212121202121200212002120112002120112002120112011202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020021100212011201021212002120021201120021201120021201120112002120112011200212011201120112021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200200211002120112011201021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201121200212002120112002120112002120112011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002020212010212010211002020202110020202110020212120021200212011202120112010212120021200212010212002110020211002120102110020211002021212002120021201120212011201102121200212002120102120021100202110021201021100202110021100212010211002021100212120021200212120021200212010211002021100202002021212002120021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201121202121200212002120112021201120102121200212002120102120021100202110021201021100202110020220210210210202102100221021021021020210210022020210202102102100220202020202100221020202020210210022020202020210022021021021020210210022102020202021021002202021020210210210022102021020210210210022021020202102102100221020202020210210022020210210202102100220202020202100220210210210202102100221020210202102102100221020210210202102100220210202020210210022102021020202102100220210202021021021000212010211002120112010212120021200212010212002120021201120212120021200212011202120112011021212002120021201021200211002021100212010211002021100212010211002021201021100212011201021201120102121200212002120102120021200212011202121200212002120112021201120110212120021200212010212002110020211002120102110020211002120102110020212010211002020211002120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002110020202102021021021021021002121200212002120102120021200212011202121200212002120112120021200212120021200212011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201121200212002120112120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002020210210202021021021021021002120102121200212002120102110020200212010212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220202102020210210022102102102102021021002210202102102021021002210202102020210210022102102020210210210022020210202102102100221020202102021021002210210202020210210002021212002120021201021100202002120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202100202121200212002120102120112121202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110020202102102102021020210202021002121200212002120102110020200212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220202102020210210022102102102102021021002210202102102021021002210202102020210210022102102020210210210022020210202102102100221020202102021021002210210202020210210002120102121200212002120102120112121202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110020202102102102020210210210210210021212002120021201021100202002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202102020210210210022102021020202102100221021021020202102100221020202102021021002210210210210202102100220210210210202102100221020202020210210022020210210202102100020202021021021021020202102102102102100212010211002021201021100202021212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100211002020202021020210210210210210021201021100202120102110020202120102110021201121200212002120102120021200212011202220020211002020211002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202021020202102100221021021021020210210022102021021020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022102102020202102100021201021212002120021201021200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212011202121201121212021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100202020202102102020210202102021021021002121200212002120102110020200212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020210020202020202021020202021021021020202100212010211002021201021100212010211002021201021100202021201021100202020212010211002020202020020202020200202020202121200212002120102110020200202020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102102020210202100221020210202102102100220210202020210210022020210202102102100221021021021020210210022020210202102102100221020202020210210022020210210202102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202020202021002210210202020210210022102021020202102100220210210210202102100220202102021021021002210210202021021021002210210202102102100220202020202100221021021020202102100220210202021021021002210202020202102100221020210210202102100221021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210202020210210022021021021020210022021021021020210022102021020210210022020202021021002202020202102100220202020210210022021021021020210002020212120021200212010212002120021201120222002021100202021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020212120021200212011202220020211002020211002120112120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002021002120102110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202020202102020202102102102020210020202020212120021200212010211002020020202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210202102021020210022021021021020210210022102102021020210210022021021021020210210022102102102102021021002210210210202102102100220210210210202102100220202020202100220202102020210210022102021020202102100221021020202102102100220202102021021021002210202021020210210022021021021020210210022102020202021021002202021020210210210022102020210202102100221021021021020210210022021021021020210210022021021021020210002021201021201021212002120021201120212011212120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110020102121212021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002010200211002120102110021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022020210202021021002210210210210202102100221020210210202102100221020210202021021002210210202021021021002202021020210210210022102020210202102100221021020202021021000212120021200212011202120112121202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100201021212120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110020102002110021201021100212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220210202021021021002210202102020210210022102102102020210210022102020210202102100221021021021020210210022021021021020210210022102020202021021002202021021020210210002121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202210202021020210210022021021021020210210022020210202102102100221020210202021021002202102020210210210022021021021020210210022102020202021021002202021020210210210022102020210202102100221021021021020210210022021021021020210210022102020202021021002202021021020210210002020202021212002120021201021100202002020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221021020202102021002210202102021021021002202102020202102100220202102021021021002210210210210202102100220202102021021021002210202020202102100220202102102021021002202020202021002210202020202102100220210210210202102100220202102020210210022020202020210022102102102020210210022021020202102102100221020202020210210022102021021020210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022021021021020210210022102021020210210210022102021021020210210022021020202021021002210202102020210210022021020202102102100221021020202102102100220210210210202100020202121200212002120112022200202110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002021002120102110020212010211002020211002120212110021100202121100211002010212021211002110020212110021100", "result": "222210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000022221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000202221021020202102021002210202102021021021002202102020202102100220202102021021021002210210210210202102100220202102021021021002210202020202102100220202102102021021002202020202021002210202020202102100220210210210202102100220202102020210210022020202020210022102102102020210210022021020202102102100221020202020210210022102021021020210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022021021021020210210022102021020210210210022102021021020210210022021020202021021002210202102020210210022021020202102102100221021020202102102100220210210210202100000" } ], - "source": "-- Shipping policy: arguments are destination, cart subtotal in cents, grams.\n-- Destinations: domestic, regional, international. Grams: 1..5000.\n-- Select v1/v2 with the same cart: domestic free shipping changes from $75 to $100.\n-- Otherwise domestic costs $4.99/$5.99, regional $9.99, international $19.99.\n-- Packages above 1kg add $2.50. Subtotals are bounded to $10,000.\n-- The bundle hash + export pins the policy used to reproduce a quote later.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nbaseRate 1 \"domestic\" = 499\nbaseRate _ \"domestic\" = 599\nbaseRate _ \"regional\" = 999\nbaseRate _ _ = 1999\n\npaidRate version zone grams = case lessEq grams 1000 of\n ^true = baseRate version zone\n _ = addBinary 250 (baseRate version zone)\n\nfreeThreshold 1 = 7500\nfreeThreshold _ = 10000\n\namount version zone subtotal grams = case and? (equal? zone \"domestic\") (lessEq (freeThreshold version) subtotal) of\n ^true = 0\n _ = paidRate version zone grams\n\nquote version zone subtotal grams = case and? (natural? subtotal) (natural? grams) of\n ^true = (case or? (equal? zone \"domestic\") (or? (equal? zone \"regional\") (equal? zone \"international\")) of\n ^true = (case and? (lessEq subtotal 1000000) (and? (lessEq 1 grams) (lessEq grams 5000)) of\n ^true = [(stringField \"status\" \"ok\") (numberField \"policyVersion\" version)\n (stringField \"destination\" zone) (numberField \"shippingCents\" (amount version zone subtotal grams))]\n _ = failure \"Subtotal must be <=1000000 cents; grams must be 1..5000.\")\n _ = failure \"Unknown destination.\")\n _ = failure \"Subtotal and grams must be canonical natural numbers.\"\n\nv1 zone subtotal grams = quote 1 zone subtotal grams\nv2 zone subtotal grams = quote 2 zone subtotal grams\n", - "sourceSha256": "6738b22bab5fe1a349404eefa0368cb4e492d6b7a6b0cf679ab4a146ee8b0aa2", - "hash": "efbdff446802ddcfe353461dce3ea75b60187fce601f0f47cfe7320511aea02e", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!export v1\n!export v2\n\n-- Shipping policy: arguments are destination, cart subtotal in cents, grams.\n-- Destinations: domestic, regional, international. Grams: 1..5000.\n-- Select v1/v2 with the same cart: domestic free shipping changes from $75 to $100.\n-- Otherwise domestic costs $4.99/$5.99, regional $9.99, international $19.99.\n-- Packages above 1kg add $2.50. Subtotals are bounded to $10,000.\n-- The bundle hash + export pins the policy used to reproduce a quote later.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies canonical-natural checks, arithmetic and Booleans.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nbaseRate 1 \"domestic\" = 499\nbaseRate _ \"domestic\" = 599\nbaseRate _ \"regional\" = 999\nbaseRate _ _ = 1999\n\npaidRate version zone grams = case lte_? grams 1000 of\n ^true = baseRate version zone\n _ = add 250 (baseRate version zone)\n\nfreeThreshold 1 = 7500\nfreeThreshold _ = 10000\n\namount version zone subtotal grams = case and? (equal? zone \"domestic\") (lte_? (freeThreshold version) subtotal) of\n ^true = 0\n _ = paidRate version zone grams\n\nquote version zone subtotal grams = case and? (isNat? subtotal) (isNat? grams) of\n ^true = (case or? (equal? zone \"domestic\") (or? (equal? zone \"regional\") (equal? zone \"international\")) of\n ^true = (case and? (lte_? subtotal 1000000) (and? (lte_? 1 grams) (lte_? grams 5000)) of\n ^true = [[\"status\" 0 \"ok\"] [\"policyVersion\" 1 version]\n [\"destination\" 0 zone] [\"shippingCents\" 1 (amount version zone subtotal grams)]]\n _ = failure \"Subtotal must be <=1000000 cents; grams must be 1..5000.\")\n _ = failure \"Unknown destination.\")\n _ = failure \"Subtotal and grams must be canonical natural numbers.\"\n\nv1 zone subtotal grams = quote 1 zone subtotal grams\nv2 zone subtotal grams = quote 2 zone subtotal grams\n", + "sourceSha256": "d6d9378ab39733a8aabaf4f6a25851350e99fa81607bf05a64266301e2712f5a", + "hash": "4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea", "mode": "pure", "haskellCases": [ { @@ -743,17 +744,6 @@ "message": "Subtotal and grams must be canonical natural numbers." } } - ], - "supportSourceSha256": "267dd96923b17f67cdce383cf464a11c4d379c8a893f05e8ea273d515283f0a2", - "baseBindings": [ - "base.isNat?", - "base.lte_?", - "base.add", - "base.and?", - "base.not?", - "base.equal?", - "base.or?", - "base.contains?" ] }, "events": { @@ -761,19 +751,19 @@ { "label": "unknown-event", "source": "q x = x x\nprobe ignored = vendorA [\"unknown\" (q q) (q q)]", - "program": "212021212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102021020202102100220202021021021021002210202020202102100221021020202021021002202021020210210210022020210210202102100221020202102102102100220202020202100220202102021021021002202020210202102100220210202021021021002210202102020210210022102021020202102100220202020202100220210210202021021002210202021020210210022102021020202102100220202102102021021002202021020202102100221021020202102102100220210210210202100020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020202020210210022020202020210022020210210202102100221020202102021021002210210202021021021002202021020210210210022021021021020210002120102120112011212011212121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021212002120021201021100202002120102110021201120112120021200212010212011212121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200212120021200212010211002020021201021212002120021212002120021212002120021201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212010212120021200212010211002020020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021201021212002120021201021100202002021100212010211002120112011201021212002120021201120021201120021201120112002120112011200212011201120102121200212002120112002120112002120112010212011200212011200212011201121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002121200212002120102110020200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201121200212002120102120021200212120021200212011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120102121200212002120102110020200212010212120021200212010211002020021201120112011201021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120021201120112011201120021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120021201120112011201120021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120112011201021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020212010211002020212010212010212010212120021200212010211002020020202120102120102120102120102121200212002120102110020200202020202021100202020202110020202120102110020202020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020210202021021002202020210210210210022102020202021021002210210202020210210022020210202102102100220202102102021021002210202021021021021002202020202021002202021020210210210022020202102021021002202102020210210210022102021020202102100221020210202021021002202020202021002202102102020210210022102020210202102100221020210202021021002202021021020210210022020210202021021002210210202021021021002202102102102021000202110020212120021200212011200212011200212011212002120021201120021201120021212002120021201120021201120021201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201021212002120021201021200212002120112120212120021200212011200212011200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112010212120021200212011200212011200212011201120021201120112002120112011201021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201021201120112011212002121202121200212002120102120021100202120121002121200211002002022102102020210210210022102102020202102100220202021020210210022102021020202102100221020210210202102100221020202020210210022021021020210202100221020210202021021002202102020210210210022102102020210210210022102020210202102100221021021021020210210022021021021020210210002021002121200212002120102120021200212010212002120021201120021201121202121200212002120102120021100202120102121200211002002022102021020202102100220210210202102102100221020210202021021002202102102102021021002202021020210210210022020210202102021002210202021021021021002202020202102102100221020210202021021000212010211002021212002120021201021200212002120112002120112120212120021200212010212002110020212010212120021100200202210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021000212010211002021212002120021201120021201121202121200212002120102120021100202120121002121200211002002022102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210002120102110020200202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221020202020210210022020202020210022102102020202102100221020202020210210022021021021020210210022102102102102021021002202102102102021021002210202021020210210022102102020202102100221020202020210210022020210210202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202102102102021000202021212002120021201120222002021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102102020210210210022102102020202102100221020202020210210022020210210202102100221020202020210210022021020202102102100220202020202100220202102021021021002210202102020210210022020202102102102100220202102021021021002202102102102021000202120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020200202120112021212120021200212120021200212010212002120021212002120021201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120102121200212002120112022200202110020202110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202102102102102102102102102102102102102102102102102020202021002120112022102002020021212002120021201120222002021100202021100212011212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100202020202020202020202020210210202102100212010211002121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002020210210210210210210210210210210210210210202102100202121200212002120102110020200202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202002120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020221021021021020210210022021020202102102100220202102020210210022102021020202102100220210202021021021002202102102102021002210210202020210210022021020202102102100221020210202021021002210202020202102100220202102021021021002210202102020210210022020210202021021000212010211002021201021100202021212002120021201021100202002120102120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020202202020202102102100221020210202102102100220210202021021021002210210202020210210022020202102021021002210202020202102100221021020202102102100221020210202021021000212120021200212011200212011200212011201120021201120112002120112011201021201121200212002120112002120112002121200212002120112002120112002120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120102121200212002120102120021200212011212021212002120021201120021201120021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201021212002120021201120021201120021201120112002120112011200212011201120102121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102120112011201121200212120212120021200212010212002110020212012100212120021100200202210210202021021021002210210202020210210022020202102021021002210202102020210210022102021021020210210022102020202021021002202102102021020210022102021020202102100220210202021021021002210210202021021021002210202021020210210022102102102102021021002202102102102021021000202100212120021200212010212002120021201021200212002120112002120112120212120021200212010212002110020212010212120021100200202210202102020210210022021021020210210210022102021020202102100220210210210202102100220202102021021021002202021020210202100221020202102102102100220202020210210210022102021020202102100021201021100202121200212002120102120021200212011200212011212021212002120021201021200211002021201021212002110020020221021020202021021002210202102021021021002210210202021021021002202021020210210210022102102102102021021002210202102102021021002210202102020210210022021020202102102100021201021100202121200212002120112002120112120212120021200212010212002110020212012100212120021100200202210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021000212010211002020020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102020202021021002202020202021002210210202020210210022102020202021021002202102102102021021002210210210210202102100220210210210202102100221020202102021021002210210202020210210022102020202021021002202021021020210210022020202020210022021021021020210210022102020202021021002202021020210210210022102021020210210210022021020202102102100221020202020210210022020210210202102100220202020202100220202102102102100221020210210210210022102020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202020202102100220210210210202100020202121200212002120112022200202110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202020202020202102020210202020202102021021021021002020202121200212002120102110020200202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221021020202021021002210202102021021021002210210202021021021002202021020210210210022102102102102021021002210202102102021021002210202102020210210022021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210210202021021021002210210202020210210022102020202021021002202021021020210210022102020202021021002202102020210210210022020202020210022020210202102102100221020210202021021002202020210210210210022020210202102102100220210210210202100020212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020020212011202121212002120021212002120021201021200212002121200212002120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212010212120021200212011202220020211002020211002121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002020210210210210210210210210210210210210210210210210202020202100212011202210200202002121200212002120112022200202110020202110021201121202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110020202020202020202020202021021020210210021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202021021021021021021021021021021021021021020210210020212120021200212010211002020020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020200212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002022102102102102021021002202102020210210210022020210202021021002210202102020210210022021020202102102100220210210210202100220210202021021021002210202102020210210022021021020202102100221020210202102102100220210210210202102100220202102020210210022102021020202102100220202102020210210002120102110020212010211002020212120021200212010211002020021201021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022021020202102102100221020210202021021002202102102020210210022102021020210210210022021021021020210210022020210202021021000202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102021020210202100220210210210202102100221021020210202102100220210210210202102100221021021021020210210022102102102021021021002202102102102021021002202020202021002202102102021021021002210202102020210210022021021021020210210022020210202021021002210210210210202102100220210202021021021002202020202021002210202020202021002202020202021002210202102020210210022021021020210210210022102021020202102100220210210210202102100220202102021021021002202102102102021000211002120122102021020210210210022021021021020210210022102102021020210210022021021021020210210022102102102102021021002210210210202102102100220210210210202102100021212002120212110021100202121100211002121200212021211002110020212110021100200", + "program": "2120212120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020210202021021002202020210210210210022102020202021021002210210202020210210022020210202102102100220202102102021021002210202021021021021002202020202021002202021020210210210022020202102021021002202102020210210210022102021020202102100221020210202021021002202020202021002202102102020210210022102020210202102100221020210202021021002202021021020210210022020210202021021002210210202021021021002202102102102021000202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021201120112120112121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212120021200212010211002020021201021100212011201121200212002120102120112121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002121200212002120102110020200212010212120021200212120021200212120021200212011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120102121200212002120102110020200202021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212010212120021200212010211002020020211002120102110021201120112010212120021200212011200212011200212011201120021201120112002120112011201021212002120021201120021201120021201120102120112002120112002120112011212120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212120021200212010211002020021212002120021201021100202002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011212002120021201021200212002121200212002120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201021212002120021201021100202002120102121200212002120102110020200212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011200212011201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011200212011201120112011200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201120112010212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202120102110020202120102120102120102121200212002120102110020200202021201021201021201021201021212002120021201021100202002020202020211002020202021100202021201021100202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022021021020202102100221020202102021021002210202102020210210022020210210202102100220202102020210210022102102020210210210022021021021020210002021100202121200212002120112002120112002120112120021200212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201121202121200212002120112002120112002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102121200212002120112002120112002120112011200212011201120021201120112010212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112010212011201120102120112011201222102102020210210210022102102020202102100220202021020210210022102021020202102100221020210210202102100221020202020210210022021021020210202100221020210202021021002202102020210210210022102102020210210210022102020210202102100221021021021020210210022021021021020210210002210022100021212002120021201021200212002120102120021201221020210202021021002202102102021021021002210202102020210210022021021021020210210022020210202102102100220202102021020210022102020210210210210022020202021021021002210202102020210210002120102121200211002002021212002120021201021200212012210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021000212010212120021100200202121200212012210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021000212012100212120021100200200202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221020202020210210022020202020210022102102020202102100221020202020210210022021021021020210210022102102102102021021002202102102102021021002210202021020210210022102102020202102100221020202020210210022020210210202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202102102102021000202021212002120021201120222002021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102102020210210210022102102020202102100221020202020210210022020210210202102100221020202020210210022021020202102102100220202020202100220202102021021021002210202102020210210022020202102102102100220202102021021021002202102102102021000202120112021212021211002110020212021212002120021201021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021201121200212002120112022200202110020202110021201120212120222002021100202021100212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002121202220020211002020211002121202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021100202102102102102102102102102102102102102102102102102020202021002120221020020200212121202121200212002120112002120112002120112011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002110020021201021100212120021200212010212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020201020202002110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020212010211002120102121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002021100211002020202020202020202020202102102021021002021021021021021021021021021021021021021020210210021201021100212010212120021200212010211002021100202110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002022102102102102021021002202102020210210210022020210202021021002210202102020210210022021020202102102100220210210210202100221021020202021021002202102020210210210022102021020202102100221020202020210210022020210202102102100221020210202021021002202021020202102100021201021100202120102110020202121200212002120102110020200212010212010212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020220202020210210210022102021020210210210022021020202102102100221021020202021021002202020210202102100221020202020210210022102102020210210210022102021020202102100021212002120021201120021201120021201120112002120112011200212011201120102120112120021200212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201121202121200212002120112002120112002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102121200212002120112002120112002120112011200212011201120021201120112010212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112010212011201120102120112011201222102102020210210210022102102020202102100220202021020210210022102021020202102100221020210210202102100221020202020210210022021021020210202100221020210202021021002202102020210210210022102102020210210210022102020210202102100221021021021020210210022021021021020210210002210022100021212002120021201021200212002120102120021201221020210202021021002202102102021021021002210202102020210210022021021021020210210022020210202102102100220202102021020210022102020210210210210022020202021021021002210202102020210210002120102121200211002002021212002120021201021200212012210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021000212010212120021100200202121200212012210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021000212012100212120021100200200202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221020202020210210022020202020210022102102020202102100221020202020210210022021021021020210210022102102102102021021002202102102102021021002210202021020210210022102102020202102100221020202020210210022020210210202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202102102102021000202021212002120021201120222002021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102102020210210210022102102020202102100221020202020210210022020210210202102100221020202020210210022021020202102102100220202020202100220202102021021021002210202102020210210022020202102102102100220202102021021021002202102102102021000202120112021212021211002110020212021212002120021201021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021201121200212002120112022200202110020202110021201120212120222002021100202021100212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002121202220020211002020211002121202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021100202102102102102102102102102102102102102102102102102020202021002120221020020200212121202121200212002120112002120112002120112011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002110020021201021100212120021200212010212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020201020202002110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020212010211002120102121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002021100211002020202020202020202020202102102021021002021021021021021021021021021021021021021020210210021201021100212010212120021200212010211002021100202110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002022102102102102021021002202102020210210210022020210202021021002210202102020210210022021020202102102100220210210210202100220210202021021021002210202102020210210022021021020202102100221020210202102102100220210210210202102100220202102020210210022102021020202102100220202102020210210002120102110020212010211002020212120021200212010211002020021201021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202022021020202102102100221020210202021021002202102102020210210022102021020210210210022021021021020210210022020210202021021000202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102021020210202100220210210210202102100221021020210202102100220210210210202102100221021021021020210210022102102102021021021002202102102102021021002202020202021002202102102021021021002210202102020210210022021021021020210210022020210202021021002210210210210202102100220210202021021021002202020202021002210202020202021002202020202021002210202102020210210022021021020210210210022102021020202102100220210210210202102100220202102021021021002202102102102021000211002120122102021020210210210022021021021020210210022102102021020210210022021021021020210210022102102102102021021002210210210202102102100220210210210202102100021212002120212110021100202121100211002121200212021211002110020212110021100200", "result": "2222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000222210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002022210202102021020210022021021021020210210022102102021020210210022021021021020210210022102102102102021021002210210210202102102100220210210210202102100220202020202100220210210202102102100221020210202021021002202102102102021021002202021020202102100221021021021020210210022021020202102102100220202020202100221020202020202100220202020202100221020210202021021002202102102021021021002210202102020210210022021021021020210210022020210202102102100220210210210202100000" }, { "label": "invalid-boolean", "source": "q x = x x\nprobe ignored = vendorB [(q q) 2 (q q)]", - "program": "2120212120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020210202021021002202020210210210210022102020202021021002210210202020210210022020210202102102100220202102102021021002210202021021021021002202020202021002202021020210210210022020202102021021002202102020210210210022102021020202102100221020210202021021002202020202021002202102102020210210022102020210202102100221020210202021021002202021021020210210022020210202021021002210210202021021021002202102102102021000202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202020202102100220202020202100220202102102021021002210202021020210210022102102020210210210022020210202102102100220210210210202100021201021201120112120112121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212120021200212010211002020021201021100212011201121200212002120102120112121212021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021212002120021201021100202002121200212002120102110020200212010212120021200212120021200212120021200212011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120102121200212002120102110020200202021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212010212120021200212010211002020020211002120102110021201120112010212120021200212011200212011200212011201120021201120112002120112011201021212002120021201120021201120021201120102120112002120112002120112011212120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212120021200212010211002020021212002120021201021100202002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011212002120021201021200212002121200212002120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201021212002120021201021100202002120102121200212002120102110020200212011201120112010212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011200212011201120112011200212120021200212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011200212011201120112011200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201120112010212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202120102110020202120102120102120102121200212002120102110020200202021201021201021201021201021212002120021201021100202002020202020211002020202021100202021201021100202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022021021020202102100221020202102021021002210202102020210210022020210210202102100220202102020210210022102102020210210210022021021021020210002021100202121200212002120112002120112002121200212002120102120021200212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201121202121200212002120112002120112002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102121200212002120112002120112002120112011200212011201120021201120112010212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112010212011201120112120021212021212002120021201021200211002021201210021212002110020020221021020202102102100221021020202021021002202020210202102100221020210202021021002210202102102021021002210202020202102100220210210202102021002210202102020210210022021020202102102100221021020202102102100221020202102021021002210210210210202102100220210210210202102100020210021212002120021201021200212002120102120021200212011200212011212021212002120021201021200211002021201021212002110020020221020210202021021002202102102021021021002210202102020210210022021021021020210210022020210202102102100220202102021020210022102020210210210210022020202021021021002210202102020210210002120102110020212120021200212010212002120021201120021201121202121200212002120102120021100202120102121200211002002022102102020202102100221020210202102102100221021020202102102100220202102021021021002210210210210202102100221020210210202102100221020210202021021002202102020210210210002120102110020212120021200212011200212011212021212002120021201021200211002021201210021212002110020020221020202020210210022102021021020210210022102102102102021021002210202102021021021002202102102102021021002202021020210210210022102102020202021002210202102020210210022021021021020210210022020210202102102100221021020202102102100021201021100202002020202121200212002120102110020200202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221020202020210210022102021021020210210022102102102102021021002210202102021021021002202102102102021021002202021020210210210022102102020202021002210202102020210210022021021021020210210022020210202102102100221021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210202020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022020210210210210022102021021021021002210202020210210022020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022021021021020210002020212120021200212011202220020211002020211002120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002020202020202020210202021020202020210202102102102100202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022102102020202102100221020210202102102100221021020202102102100220202102021021021002210210210210202102100221020210210202102100221020210202021021002202102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221021020202102102100221021020202021021002210202020202102100220202102102021021002210202020202102100220210202021021021002202020202021002202021020210210210022102021020202102100220202021021021021002202021020210210210022021021021020210002021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202002021201120212121200212002121200212002120102120021200212120021200212011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201021212002120021201120222002021100202021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202021021021021021021021021021021021021021021021021020202020210021201120221020020200212120021200212011202220020211002020211002120112120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002020202020202020202020202102102021021002120102110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202102102102102102102102102102102102102102021021002021212002120021201021100202002021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020021202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021100212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202210210210210202102100220210202021021021002202021020202102100221020210202021021002202102020210210210022021021021020210022021020202102102100221020210202021021002202102102020210210022102021020210210210022021021021020210210022020210202021021002210202102020210210022020210202021021000212010211002021201021100202021212002120021201021100202002021201021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010212120021200212011200212011200212011201120021201120112002120112011201021212002120021201021200212002120112002120112002121200212002120112002120112002120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120102121200212002120102120021200212011212021212002120021201120021201120021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201021212002120021201120021201120021201120112002120112011200212011201120102121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102120112011201121200212120212120021200212010212002110020212012100212120021100200202210210202021021021002210210202020210210022020202102021021002210202102020210210022102021021020210210022102020202021021002202102102021020210022102021020202102100220210202021021021002210210202021021021002210202021020210210022102102102102021021002202102102102021021000202100212120021200212010212002120021201021200212002120112002120112120212120021200212010212002110020212010212120021100200202210202102020210210022021021020210210210022102021020202102100220210210210202102100220202102021021021002202021020210202100221020202102102102100220202020210210210022102021020202102100021201021100202121200212002120102120021200212011200212011212021212002120021201021200211002021201021212002110020020221021020202021021002210202102021021021002210210202021021021002202021020210210210022102102102102021021002210202102102021021002210202102020210210022021020202102102100021201021100202121200212002120112002120112120212120021200212010212002110020212012100212120021100200202210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021000212010211002020020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021212002121202121200212002120102120021100202120102121200211002002022102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100021212002121202121200212002120102120021100202120102121200211002002022102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021100200202210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102020202021021002202020202021002210210202020210210022102020202021021002202102102102021021002210210210210202102100220210210210202102100221020202102021021002210210202020210210022102020202021021002202021021020210210022020202020210022021021021020210210022102020202021021002202021020210210210022102021020210210210022021020202102102100221020202020210210022020210210202102100220202020202100220202102102102100221020210210210210022102020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202020202102100220210210210202100020202121200212002120112022200202110020202110021201120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020202020202020202102020210202020202102021021021021002020202121200212002120102110020200202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202021202121200212120212120021200212010212002110020212010212120021100200202210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210002121200212120212120021200212010212002110020212010212120021100200202210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002110020020221021020202021021002210202102021021021002210210202021021021002202021020210210210022102102102102021021002210202102102021021002210202102020210210022021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210210202021021021002210210202020210210022102020202021021002202021021020210210022102020202021021002202102020210210210022020202020210022020210202102102100221020210202021021002202020210210210210022020210202102102100220210210210202100020212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020020212011202121212002120021212002120021201021200212002121200212002120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212010212120021200212011202220020211002020211002121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002020210210210210210210210210210210210210210210210210202020202100212011202210200202002121200212002120112022200202110020202110021201121202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110020202020202020202020202021021020210210021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202021021021021021021021021021021021021021020210210020212120021200212010211002020020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020200212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002022102102102102021021002202102020210210210022020210202021021002210202102020210210022021020202102102100220210210210202100221021020202021021002202102020210210210022102021020202102100221020202020210210022020210202102102100221020210202021021002202021020202102100021201021100202120102110020202121200212002120102110020200202120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020200202020202120212120021212021212002120021201021200211002021201021212002110020020221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000212120021212021212002120021201021200211002021201021212002110020020221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000211002002022021020202102102100221020210202021021002202102102020210210022102021020210210210022021021021020210210022020210202021021002210202102020210210022020210202021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102020202021021002202020202021002210210202020210210022102020202021021002202102102102021021002210210210210202102100220210210210202102100221020202102021021002210210202020210210022102020202021021002202021021020210210022020202020210022021020202020210022102102102102021021002210210210210202102100220202102102021021002210202102020210210022102020202021021002202102102102021021002202102102102021000211002121200212021211002110020212110021100212012021002121200212021211002110020212110021100200", + "program": "21202121202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102021020202021002202020210210210210022020202021021021002210202102020210210022102102020202102100220202102021021021002210202102020210210022020210202021021002202020202021002210202102020210210022020202102102102100221020202020210210022102102020202102100220202102021021021002202021021020210210022102020210210210210022020202020210022020210202102102100220202021020210210022021020202102102100221020210202021021002210202102020210210022020202020210022021021020202102100221020202102021021002210202102020210210022020210210202102100220202102020210210022102102020210210210022021021021020210002021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102020202021021002202020202021002202021021020210210022102020210202102100221021020202102102100220202102021021021002202102102102021000212010212011201121201121212120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212120021200212010211002020020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020202020210210022020202020210022020210210202102100221020202102021021002210210202021021021002202021020210210210022021021021020210002120102121200212002120102110020200212010211002120112011212002120021201021201121212120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212120021200212010211002020021212002120021201021100202002120102121200212002121200212002121200212002120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201021212002120021201021100202002020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210202102020202100220202021021021021002202020202102102100221020210202021021002210210202020210210022020210202102102100221020210202021021002202021020202102100220202020202100221020202020210210022020202020210022020210210202102100221020202102021021002210210202021021021002202021020210210210022021021021020210002120102120102121200212002120102110020200202110021201021100212011201120102121200212002120112002120112002120112011200212011201120021201120112010212120021200212011200212011200212011201021201120021201120021201120112121202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002121200212002120102110020200212120021200212010211002020021212002120021201120021201120021201120112002120112011200212011201120112002120112011201120021201120112120021200212010212002120021212002120021201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212010212120021200212010211002020021201021212002120021201021100202002120112011201120102121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120112002120112011201120112002121200212002120112002120112002120112011200212011201120021201120112011200212011201120112002120112011201120112002120112011201120112002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120021201120112011200212011201120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112011201120102121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021201021100202021201021201021201021212002120021201021100202002020212010212010212010212010212120021200212010211002020020202020202110020202020211002020212010211002020202021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221020210202020210022020202102102102100220202020210210210022102021020202102100221021020202021021002202021020210210210022102021020202102100220202102020210210022020202020210022102021020202102100220202021021021021002210202020202102100221021020202021021002202021020210210210022020210210202102100221020202102102102100220202020202100220202102021021021002202020210202102100220210202021021021002210202102020210210022102021020202102100220202020202100220210210202021021002210202021020210210022102021020202102100220202102102021021002202021020202102100221021020202102102100220210210210202100020211002021212002120021201120021201120021212002120021201021200212002120112002120112002121200212002120112002120112002120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120102121200212002120102120021200212011212021212002120021201120021201120021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201021201120112002120112011200212120021200212011200212011200212011201120021201120112002120112011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112011201021212002120021201120021201120021201120112002120112011200212011201120102121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102120112011201021201120112012221021020202102102100221021020202021021002202020210202102100221020210202021021002210202102102021021002210202020202102100220210210202102021002210202102020210210022021020202102102100221021020202102102100221020202102021021002210210210210202102100220210210210202102100022100221000212120021200212010212002120021201021200212012210202102020210210022021021020210210210022102021020202102100220210210210202102100220202102021021021002202021020210202100221020202102102102100220202020210210210022102021020202102100021201021212002110020020212120021200212010212002120122102102020202102100221020210202102102100221021020202102102100220202102021021021002210210210210202102100221020210210202102100221020210202021021002202102020210210210002120102121200211002002021212002120122102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210002120121002121200211002002002020202121200212002120102110020200202020212120021200212011202121201121211002110021201021100202120212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020020202002121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212120021200212010211002021100202020200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200212120021200212011200212011200212011201021201120021201120021201120112002120112011200212011201120112022200202110020202110021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002121202121200212002120102120021200212120021200212010212002120021100202120102110020212010211002021211002110021100212010211002020102020202021202120122210210202021021021002202021020210210210022102020202021021002202021020210210210022102021020210210210022102102020210210210002022210202102020210210022021020202102102100220210202021021021002210210210210202102100220210202021021021000021212002120122102021021020210210022102021020202102100221021020202102102100221021020202102102100221020202020210210022102102102020210210022102021020202102100021201021212002110020020020221020202020210210022102021021020210210022102102102102021021002210202102021021021002202102102102021021002202021020210210210022102102020202021002210202102020210210022021021021020210210022020210202102102100221021020202102102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210202020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102102102021021002210202020202102100220202102021021021002210202102021021021002202102020210210210022102020202021021002202021021020210210022020202020210022020210210210210022102021021021021002210202020210210022020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022021021021020210002020212120021200212011202220020211002020211002120112021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002020202020202020210202021020202020210202102102102100202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102102020202102100221020210202102102100221021020202102102100220202102021021021002210210210210202102100221020210210202102100221020210202021021002202102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221021020202102102100221021020202021021002210202020202102100220202102102021021002210202020202102100220210202021021021002202020202021002202021020210210210022102021020202102100220202021021021021002202021020210210210022021021021020210002021201120212120212110021100202120212120021200212010212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212011212002120021201120222002021100202021100212011202121202220020211002020211002120212120212110021100202120212120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200212010212120021200212010212002120021212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201120021201120021201120102121200212002120112002120112002121200212002120112002120112002120112011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021201120102121200212002120102120021200212010211002021201021100212011201021201120102121200212002120102120021200212010211002021201021100202021100202120102110021201120102121200212002120112002120112002121200212002120112002120112002120112010212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212011201120112021211002002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110020212010212120021200212010212002120021201021100202120102110020202120102121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110020202021100212011201021212002120021201021200212002120102110020212010211002020212120021200212010211002020020202120102121200212002120102110020200202021201021100202020200202020202002020211002021201021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002110021212022200202110020202110021212021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100211002021021021021021021021021021021021021021021021021020202020210021202210200202002121212021212002120021201120021201120021201120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021100200212010211002121200212002120102120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202010202020021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202120102110021201021212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020211002110020202020202020202020202021021020210210020210210210210210210210210210210210210210202102100212010211002120102121200212002120102110020211002021100202110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020221021021021020210210022021020202102102100220202102020210210022102021020202102100220210202021021021002202102102102021002202102020210210210022102021020202102100220210210202021021002210202102021021021002202102102102021021002202021020202102100221020210202021021002202021020202102100021201021100202120102110020202121200212002120102110020200202120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201021212002120021201120021201120021201120112002120112011200212011201120102121200212002120102120021200212011200212011200212120021200212011200212011200212011201120212011201120212110020021212002120021201120021201120021212002120021201021200212002120112021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002110021201021201021100212010212010212010211002120102110020212010211002020211002120112010212120021200212010212002120021201121202121200212002120112002120112002121200212002120112002120112002120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120102120112011200212011201120021212002120021201120021201120021201120112002120112011200212011201120112021201120112021211002002121200212002120112002120112002121200212002120102120021200212011202121200212002120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100211002120102120102110021201021201021201021100212010211002021201021100202021100212011201120102121200212002120112002120112002120112011200212011201120021201120112010212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112010212011201120021201120112002121200212002120112002120112002120112011200212011201120021201120112011202120112011202121100200212120021200212011200212011200212120021200212010212002120021201120212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021100212010212010211002120102120102120102110021201021100202120102110020202110021201120112010212011201120102120112011201222102102020210210210022102102020202102100220202021020210210022102021020202102100221020210210202102100221020202020210210022021021020210202100221020210202021021002202102020210210210022102102020210210210022102020210202102100221021021021020210210022021021021020210210002210022100021212002120021201021200212002120102120021201221020210202021021002202102102021021021002210202102020210210022021021021020210210022020210202102102100220202102021020210022102020210210210210022020202021021021002210202102020210210002120102121200211002002021212002120021201021200212012210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021000212010212120021100200202121200212012210202020202102100221020210210202102100221021021021020210210022102021020210210210022021021021020210210022020210202102102100221021020202020210022102021020202102100220210210210202102100220202102021021021002210210202021021021000212012100212120021100200200202020212120021200212010211002020020202021212002120021201120212120112121100211002120102110020212021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002020200212120021200212011212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020021212002120021201021100202110020202020021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020021212002120021201120021201120021201120102120112002120112002120112011200212011201120021201120112011202220020211002020211002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201021100202120102110020202120102110021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100212120212120021200212010212002120021212002120021201021200212002110020212010211002021201021100202121100211002110021201021100202010202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022102020202021021002210202102102021021002210210210210202102100221020210202102102100220210210210202102100220202102021021021002210210202020202100221020210202021021002202102102102021021002202021020210210210022102102020210210210022020202020210022102021021020210210022102021020210210210022102102020210210210022020210202102102100220202020202100220210202020210210022102021020202102100220202020202100221020202020210210022020202020210022102102020202102100221020202020210210022021021021020210210022102102102102021021002202102102102021021002210202021020210210022102102020202102100221020202020210210022020210210202102100220202020202100220210210210202102100221020202020210210022020210202102102100221020210202102102100220210202021021021002210202020202102100220202102102021021002202020202021002202021021021021002210202102102102100221020202021021002202020202102100220202020210210022020202021021002202020202102100220202020210210022020202021021002202102102102021000202021212002120021201120222002021100202021100212011202121202121100211002021202121200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002010202002120102121200212002120102120021200212120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212011200212011200212011201021212002120021201120021201120021212002120021201120021201120021201120112120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200212011201021212002120021201021200212002120102110020212010211002120112010212011201021212002120021201021200212002120102110020212010211002020211002021201021100212011201021212002120021201120021201120021212002120021201120021201120021201120102120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202120112011201120212110020021212002120021201120021201120021201120112002120112011200212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100202120102121200212002120102120021200212010211002021201021100202021201021212002120021201120021201120021201120102120112002120112002121200212002120102120021200212010211002021201021100202021201021100202020211002120112010212120021200212010212002120021201021100202120102110020202121200212002120102110020200202021201021212002120021201021100202002020212010211002020202002020202020020202110020212010211002021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100212120021200212011202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021201021100202020202020202021020202102020202021020210210210210020202021212002120021201021100202002020202121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020201020202020212021201222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000212120021201221020210210202102100221020210202021021002210210202021021021002210210202021021021002210202020202102100221021021020202102100221020210202021021000212010212120021100200200202210210202020210210022102021020210210210022102102020210210210022020210202102102100221021021021020210210022102021021020210210022102021020202102100220210202021021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102102020210210210022102102020202102100221020202020210210022020210210202102100221020202020210210022021020202102102100220202020202100220202102021021021002210202102020210210022020202102102102100220202102021021021002202102102102021000202120112021212021211002110020212021212002120021201021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021201121200212002120112022200202110020202110021201120212120222002021100202021100212021212021211002110020212021212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020102020021201021212002120021201021200212002121200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120112002120112002120112010212120021200212011200212011200212120021200212011200212011200212011201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002120112010212120021200212010212002120021201021100202120102110021201120102120112010212120021200212010212002120021201021100202120102110020202110020212010211002120112010212120021200212011200212011200212120021200212011200212011200212011201021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021201120112011202121100200212120021200212011200212011200212011201120021201120112002121200212002120112002120112002120112010212011200212011200212120021200212010212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002021201021212002120021201021200212002120102110020212010211002020212010212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002020202110021201120102121200212002120102120021200212010211002021201021100202021212002120021201021100202002020212010212120021200212010211002020020202120102110020202020020202020200202021100202120102110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100211002121202220020211002020211002121202120112021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200201021100212011202121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100212120021200212011202121202121100211002021202121200212002120102120021200212011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020200202020102110020200212120021200212010212002120021201120021201120021201120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002020020200212011212002120021201021200212002120112002120112002121200212002120112002120112002121200212002120112002120112002120112011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121200212002120102120021200212011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020200211002121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020102002110021201021100212010211002021201021100202020201020202020202002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212010212010211002021201021100212120212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110020212110021100211002110021201021100202110021100202102102102102102102102102102102102102102102102102020202021002120221020020200212121202121200212002120112002120112002120112011202120112121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002110020021201021100212120021200212010212002120021201120212011202121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110020020102110021201120212121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020020201020202002110021212002120021201120212120212110021100202120212120021200212010212002120021201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002020021212002120021201021200212002120112002120112002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100202002020021201121200212002120102120021200212011200212011200212120021200212011200212011200212120021200212011200212011200212011201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212120021200212010212002120021201120212011212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002020021100212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002010200211002120102110021201021100202120102110020202020102020202020200212010212011201021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021201021201021100202120102110021212021212002120021201120021201120021212002120021201021200212002120102110020212010211002020211002021211002110021100211002120102110020211002120102110020212010211002120102121200212002120112021201120212121202121200212002120112002120112002121200212002120112002120112002120112120021200212011202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002120102110021201021201021201021100212010212010212010212010211002020211002002010211002120112021212121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002020020202010211002121200212002120112021212021211002110020212021212002120021201021200212002120112121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002121212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002020201021100202002121200212002120102120021200212011200212011200212011201121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110020200202002120112120021200212010212002120021201120021201120021212002120021201120021201120021212002120021201120021201120021201120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212002120021201021200212002120112021201121212021212002120021201120021201120021212002120021201120021201120021201121200212002120112021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021201021100212010212010212010211002120102120102120102120102110020202110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100200202002110021212120212120021200212011200212011200212120021200212011200212011200212011212002120021201120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100212010211002120102120102120102110021201021201021201021201021100202021100201020021100212010211002120102110020212010211002020202010202020202020021201021201120102121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202120102120102110020212010211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002021100212010211002021100211002020202020202020202020202102102021021002021021021021021021021021021021021021021020210210021201021100212010212120021200212010211002021100202110020211002121202121200212002120112002120112002121200212002120102120021200212010211002021201021100202021100202121100211002110021100212010211002022102102102102021021002202102020210210210022020210202021021002210202102020210210022021020202102102100220210210210202100221021020202021021002202102020210210210022102021020202102100221020202020210210022020210202102102100221020210202021021002202021020202102100021201021100202120102110020202121200212002120102110020200202120102121200212002120112021212011212110021100212010211002021202121212021212002120021201120021201120021201120102120112002121200212002120102120021100202110020202110021212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100201020200202020021212002120021201121202121200212002120112002120112002120112010212011200212120021200212010212002110020211002020211002002121200212002120102110020211002020202002120112011212120212120021200212011200212011200212011201021201120021212002120021201021200211002021100202021100200202002121200212002120112002120112002120112010212011200212011200212011201120021201120112002120112011201120222002021100202021100212120021200212011200212011200212011201021201120021201120021212002120021201021200212002120102110020212010211002020212010211002120102120112010212120021200212011200212011200212120021200212010212002120021201021100202120102110020202110021212021212002120021201021200212002121200212002120102120021200211002021201021100202120102110020212110021100211002120102110020200202020202120212012221021020202102102100220202102021021021002210202020202102100220202102021021021002210202102021021021002210210202021021021000202221020210202021021002202102020210210210022021020202102102100221021021021020210210022021020202102102100002121200212012210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002120102121200211002002002022021020202102102100221020210202021021002202102102020210210022102021020210210210022021021021020210210022020210202021021002210202102020210210022020210202021021002202020202021002210202102102021021002210202102021021021002210210202021021021002202021020210210210022020202020210022021020202021021002210202102020210210022020202020210022102020202021021002202020202021002210210202020210210022102020202021021002202102102102021021002210210210210202102100220210210210202102100221020202102021021002210210202020210210022102020202021021002202021021020210210022020202020210022021020202020210022102102102102021021002210210210210202102100220202102102021021002210202102020210210022102020202021021002202102102102021021002202102102102021000211002121200212021211002110020212110021100212012021002121200212021211002110020212110021100200", "result": "2222102102020210210210022020210202102102100221020202020210210022020210202102102100221020210202102102100221021020202102102100020222102021020202102100220210202021021021002202102020210210210022102102102102021021002202102020210210210000222210202102102021021002210202102020210210022102102020210210210022102102020210210210022102020202021021002210210210202021021002210202102020210210002022202102020210210210022102021020202102100220210210202021021002210202102021021021002202102102102021021002202021020202102100221020210202021021002202021020202102100220202020202100221020210210202102100221020210202102102100221021020202102102100220202102021021021002202020202021002202102020202102100221020210202021021002202020202021002210202020202102100220202020202100221021020202021021002210202020202102100220210210210202102100221021021021020210210022021021021020210210022102020210202102100221021020202021021002210202020202102100220202102102021021002202020202021002202102020202021002210210210210202102100221021021021020210210022020210210202102100221020210202021021002210202020202102100220210210210202102100220210210210202100000" } ], - "source": "-- Event adapter: two producers, one consumer-facing record schema.\n-- vendorA accepts [eventName customer totalCents]. eventName is purchase/refund.\n-- vendorB accepts [customer refunded totalCents]. refunded is a Boolean.\n-- Both return schemaVersion, eventType, customer and amountCents.\n-- Try the two exports: their presets describe the same order.created event.\n-- A producer can publish the adapter hash alongside its event schema.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nnormalized event customer cents = case text? customer of\n ^true = (case and? (natural? cents) (lessEq cents 1000000) of\n ^true = [(numberField \"schemaVersion\" 1) (stringField \"eventType\" event)\n (stringField \"customer\" customer) (numberField \"amountCents\" cents)]\n _ = failure \"amountCents must be a canonical natural <=1000000.\")\n _ = failure \"customer must be scalar text.\"\n\nfromA \"purchase\" customer cents = normalized \"order.created\" customer cents\nfromA \"refund\" customer cents = normalized \"order.refunded\" customer cents\nfromA _ _ _ = failure \"Unknown vendor A event.\"\n\nfromB customer ^true cents = normalized \"order.refunded\" customer cents\nfromB customer ^false cents = normalized \"order.created\" customer cents\nfromB _ _ _ = failure \"refunded must be a canonical Boolean.\"\n\n-- Preserve list-shape diagnostics without inspecting any field before dispatch.\nunpack handler (t _) = failure \"Expected a list.\"\nunpack handler [_ | (t _)] = failure \"Expected a list.\"\nunpack handler [_ | [_ | (t _)]] = failure \"Expected a list.\"\nunpack handler [a b c] = handler a b c\nunpack _ _ = failure \"Expected exactly three fields.\"\n\nvendorA values = unpack fromA values\nvendorB values = unpack fromB values\n", - "sourceSha256": "c0a6deee9945ae50a71c68461030af7cdbce30495bb6d154b98e393bb70280a1", - "hash": "0844067dd63e9e6fc252a2ab2343b1937bb31abd8e44ad6683895f81d0c2499c", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export vendorA\n!export vendorB\n\n-- Event adapter: two producers, one consumer-facing record schema.\n-- vendorA accepts [eventName customer totalCents]. eventName is purchase/refund.\n-- vendorB accepts [customer refunded totalCents]. refunded is a Boolean.\n-- Both return schemaVersion, eventType, customer and amountCents.\n-- Try the two exports: their presets describe the same order.created event.\n-- A producer can publish the adapter hash alongside its event schema.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nnormalized event customer cents = case A.hostString? customer of\n ^true = (case and? (isNat? cents) (lte_? cents 1000000) of\n ^true = [[\"schemaVersion\" 1 1] [\"eventType\" 0 event]\n [\"customer\" 0 customer] [\"amountCents\" 1 cents]]\n _ = failure \"amountCents must be a canonical natural <=1000000.\")\n _ = failure \"customer must be scalar text.\"\n\nfromA \"purchase\" customer cents = normalized \"order.created\" customer cents\nfromA \"refund\" customer cents = normalized \"order.refunded\" customer cents\nfromA _ _ _ = failure \"Unknown vendor A event.\"\n\nfromB customer ^true cents = normalized \"order.refunded\" customer cents\nfromB customer ^false cents = normalized \"order.created\" customer cents\nfromB _ _ _ = failure \"refunded must be a canonical Boolean.\"\n\n-- Preserve list-shape diagnostics without inspecting any field before dispatch.\nunpack handler (t _) = failure \"Expected a list.\"\nunpack handler [_ | (t _)] = failure \"Expected a list.\"\nunpack handler [_ | [_ | (t _)]] = failure \"Expected a list.\"\nunpack handler [a b c] = handler a b c\nunpack _ _ = failure \"Expected exactly three fields.\"\n\nvendorA values = unpack fromA values\nvendorB values = unpack fromB values\n", + "sourceSha256": "ca11d9a7e20bfe228545c43f50aed57089c020eead516e23b67d909fae8923de", + "hash": "8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb", "mode": "pure", "haskellCases": [ { @@ -1151,24 +1141,13 @@ "message": "amountCents must be a canonical natural <=1000000." } } - ], - "supportSourceSha256": "267dd96923b17f67cdce383cf464a11c4d379c8a893f05e8ea273d515283f0a2", - "baseBindings": [ - "base.isNat?", - "base.lte_?", - "base.add", - "base.and?", - "base.not?", - "base.equal?", - "base.or?", - "base.contains?" ] }, "registration": { "demandCases": [], - "source": "-- Registration validator: name, email, age, termsAccepted are separate arguments.\n-- Returns one field-specific message per input, plus an accepted Boolean.\n-- Name must be nonempty scalar text. Age must be a natural from 18 to 120.\n-- Email uses a deliberately small rule: nonempty text containing @ and a dot.\n-- Terms must be the canonical true Boolean. This is a teaching policy, not SMTP validation.\n-- Browser and server can pin this same executable instead of duplicating rules.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nnameMessage name = case text? name of\n ^true = (case name of\n [] = \"Name is required.\"\n _ = \"\")\n _ = \"Name must be scalar text.\"\n\nemailMessage email = case text? email of\n ^true = (case and? (contains? \"@\" email) (contains? \".\" email) of\n ^true = \"\"\n _ = \"Email must contain @ and a dot.\")\n _ = \"Email must be scalar text.\"\n\nageMessage age = case natural? age of\n ^true = (case and? (lessEq 18 age) (lessEq age 120) of\n ^true = \"\"\n _ = \"Age must be from 18 to 120.\")\n _ = \"Age must be a canonical natural.\"\n\ntermsMessage ^true = \"\"\ntermsMessage _ = \"Accept the terms.\"\n\nreport name email age terms = [\n (boolField \"accepted\" (and? (equal? name \"\") (and? (equal? email \"\") (and? (equal? age \"\") (equal? terms \"\")))))\n (stringField \"nameError\" name) (stringField \"emailError\" email)\n (stringField \"ageError\" age) (stringField \"termsError\" terms)]\n\nmain name email age terms = report (nameMessage name) (emailMessage email) (ageMessage age) (termsMessage terms)\n", - "sourceSha256": "bc01d7b3af0dabb3c467aa06e48d7c18118276bc087dda0ea867f8a1a660ef05", - "hash": "a8ea6cb0c1d175206448456e907790f5204f43c48581f588ddb4894d4c40b996", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export main\n\n-- Registration validator: name, email, age, termsAccepted are separate arguments.\n-- Returns one field-specific message per input, plus an accepted Boolean.\n-- Name must be nonempty scalar text. Age must be a natural from 18 to 120.\n-- Email uses a deliberately small rule: nonempty text containing @ and a dot.\n-- Terms must be the canonical true Boolean. This is a teaching policy, not SMTP validation.\n-- Browser and server can pin this same executable instead of duplicating rules.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nnameMessage name = case A.hostString? name of\n ^true = (case name of\n [] = \"Name is required.\"\n _ = \"\")\n _ = \"Name must be scalar text.\"\n\nemailMessage email = case A.hostString? email of\n ^true = (case and? (contains? \"@\" email) (contains? \".\" email) of\n ^true = \"\"\n _ = \"Email must contain @ and a dot.\")\n _ = \"Email must be scalar text.\"\n\nageMessage age = case isNat? age of\n ^true = (case and? (lte_? 18 age) (lte_? age 120) of\n ^true = \"\"\n _ = \"Age must be from 18 to 120.\")\n _ = \"Age must be a canonical natural.\"\n\ntermsMessage ^true = \"\"\ntermsMessage _ = \"Accept the terms.\"\n\nreport name email age terms = [\n [\"accepted\" 2 (and? (equal? name \"\") (and? (equal? email \"\") (and? (equal? age \"\") (equal? terms \"\"))))]\n [\"nameError\" 0 name] [\"emailError\" 0 email]\n [\"ageError\" 0 age] [\"termsError\" 0 terms]]\n\nmain name email age terms = report (nameMessage name) (emailMessage email) (ageMessage age) (termsMessage terms)\n", + "sourceSha256": "531866c6b2e7e42ecbd4ae285c502b59321ad31fd2b82b36d8a139938592ac31", + "hash": "679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a", "mode": "pure", "haskellCases": [ { @@ -1285,24 +1264,13 @@ "termsError": "Accept the terms." } } - ], - "supportSourceSha256": "267dd96923b17f67cdce383cf464a11c4d379c8a893f05e8ea273d515283f0a2", - "baseBindings": [ - "base.isNat?", - "base.lte_?", - "base.add", - "base.and?", - "base.not?", - "base.equal?", - "base.or?", - "base.contains?" ] }, "migration": { "demandCases": [], - "source": "-- Archived profile v0: [name email]. v1: adds schemaVersion and displayName.\n-- v2: also supplies marketingOptIn=false; existing data is preserved.\n-- Select v1/v2 with the same input to compare the two target schemas.\n-- A migration receipt can record the input identity, executable hash/export,\n-- output identity and wire schema. Running this demo stays entirely local.\n-- Preparation closes practical-support.tri and selected base helpers into code.\n\nmigrate version name email = case and? (text? name) (text? email) of\n ^true = (case version of\n 1 = [(numberField \"schemaVersion\" 1) (stringField \"displayName\" name) (stringField \"email\" email)]\n _ = [(numberField \"schemaVersion\" 2) (stringField \"displayName\" name) (stringField \"email\" email)\n (boolField \"marketingOptIn\" false)])\n _ = failure \"Name and email must be scalar text.\"\n\nprofile _ (t _) = failure \"Expected a list.\"\nprofile _ [_ | (t _)] = failure \"Expected a list.\"\nprofile version [name email] = migrate version name email\nprofile _ _ = failure \"Expected [name email].\"\n\nv1 values = profile 1 values\nv2 values = profile 2 values\n", - "sourceSha256": "3f8b8125203b08e6e57b83f509b445e08c882da6fe507efe338bfde0649f3f8a", - "hash": "41f27e53f2cde13130dc5a9c3e74de49d16f94f7dc565ca4357c55ce4ba5280d", + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 *\n!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A\n!export v1\n!export v2\n\n-- Archived profile v0: [name email]. v1: adds schemaVersion and displayName.\n-- v2: also supplies marketingOptIn=false; existing data is preserved.\n-- Select v1/v2 with the same input to compare the two target schemas.\n-- A migration receipt can record the input identity, executable hash/export,\n-- output identity and wire schema. Running this demo stays entirely local.\n-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean.\n-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text.\n\nfailure message = [[\"status\" 0 \"error\"] [\"message\" 0 message]]\n\nmigrate version name email = case and? (A.hostString? name) (A.hostString? email) of\n ^true = (case version of\n 1 = [[\"schemaVersion\" 1 1] [\"displayName\" 0 name] [\"email\" 0 email]]\n _ = [[\"schemaVersion\" 1 2] [\"displayName\" 0 name] [\"email\" 0 email]\n [\"marketingOptIn\" 2 false]])\n _ = failure \"Name and email must be scalar text.\"\n\nprofile _ (t _) = failure \"Expected a list.\"\nprofile _ [_ | (t _)] = failure \"Expected a list.\"\nprofile version [name email] = migrate version name email\nprofile _ _ = failure \"Expected [name email].\"\n\nv1 values = profile 1 values\nv2 values = profile 2 values\n", + "sourceSha256": "66ee7bc1a9005b5f1d12f168b7866231ad7f523cf34f52b63958cb155a5c49b5", + "hash": "730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3", "mode": "pure", "haskellCases": [ { @@ -1626,17 +1594,6 @@ "message": "Name and email must be scalar text." } } - ], - "supportSourceSha256": "267dd96923b17f67cdce383cf464a11c4d379c8a893f05e8ea273d515283f0a2", - "baseBindings": [ - "base.isNat?", - "base.lte_?", - "base.add", - "base.and?", - "base.not?", - "base.equal?", - "base.or?", - "base.contains?" ] } }, diff --git a/ext/demo-site/demos/events.tri b/ext/demo-site/demos/events.tri @@ -1,15 +1,23 @@ +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 * +!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A +!export vendorA +!export vendorB + -- Event adapter: two producers, one consumer-facing record schema. -- vendorA accepts [eventName customer totalCents]. eventName is purchase/refund. -- vendorB accepts [customer refunded totalCents]. refunded is a Boolean. -- Both return schemaVersion, eventType, customer and amountCents. -- Try the two exports: their presets describe the same order.created event. -- A producer can publish the adapter hash alongside its event schema. --- Preparation closes practical-support.tri and selected base helpers into code. +-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean. +-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text. + +failure message = [["status" 0 "error"] ["message" 0 message]] -normalized event customer cents = case text? customer of - ^true = (case and? (natural? cents) (lessEq cents 1000000) of - ^true = [(numberField "schemaVersion" 1) (stringField "eventType" event) - (stringField "customer" customer) (numberField "amountCents" cents)] +normalized event customer cents = case A.hostString? customer of + ^true = (case and? (isNat? cents) (lte_? cents 1000000) of + ^true = [["schemaVersion" 1 1] ["eventType" 0 event] + ["customer" 0 customer] ["amountCents" 1 cents]] _ = failure "amountCents must be a canonical natural <=1000000.") _ = failure "customer must be scalar text." diff --git a/ext/demo-site/demos/greet.tri b/ext/demo-site/demos/greet.tri @@ -1,14 +1,14 @@ --- Standalone browser demo: constructors match lib/io.tri version 1. -io action = t "tricuIO" (t 1 action) -pure value = t 0 value -bind action k = t 1 (t action k) -putStr text = t 10 text -getLine = t 11 t +!import 2d23be85d277457fd36c84f5eaa227e94e1c4efec281ff73017aaee109096f49 as IO +!export main -main = (io (do bind - putStr "What is your name?\n" - name <- getLine - putStr "Hello, " - putStr name - putStr "!\n" - pure name)) +-- A conversation built from the IO library's actions and explicit bind operator. +-- Evaluate main in Browser IO mode, then answer in the terminal input. +-- The returned name is also displayed as Text. Try changing the greeting. +-- Importing IO does not grant filesystem or network access in the browser. +main = (IO.io (do IO.bind + IO.putStr "What is your name?\n" + name <- IO.getLine + IO.putStr "Hello, " + IO.putStr name + IO.putStr "!\n" + IO.pure name)) diff --git a/ext/demo-site/demos/intro.tri b/ext/demo-site/demos/intro.tri @@ -1,42 +1,47 @@ +!export * + -- Start here: a small tricu language guide. -- Lines beginning with -- are comments. Read down, then try the exports. --- Choose an export in the right panel; its suggested inputs load for you. +-- Edit this source in place; valid edits compile after a short pause. +-- Write a call in Evaluate tricu expression, then press Evaluate. +-- Imports/exports declare a module; this introductory one needs no libraries. -- 1. Definitions give a name to a value: name = expression. -- Every value is a tree. These are the three constructor forms. leaf = t stem = t t fork = t t t --- Select leaf, stem or fork with Tree graph to see its structure. +-- Evaluate leaf, stem or fork with tricu · t source to see its structure. -- 2. A lambda names an input before the colon and returns an expression. identity = (x : x) --- Select identity: try a string argument, then a number with Natural number. +-- Try identity "Hello!" with Text, then identity 42 with Natural number. -- 3. Named parameters are a convenient way to write functions. -- This is equivalent to first = (a b : a). first a b = a --- Select first: it returns the first of its two arguments. +-- Try first 7 9: it returns the first of its two arguments. -- 4. Application is written with spaces and groups to the left. -- first 7 9 means (first 7) 9. Parentheses group an expression explicitly. answer = identity (first 42 7) --- Select answer with [] arguments and Natural number: the result is 42. --- [] in the arguments box means this definition needs no further inputs. +-- Evaluate answer with Natural number: the result is 42. +-- A name by itself needs no further arguments; [] is an empty-list value. -- 5. Numbers, quoted strings and lists are convenient tree literals. greeting = "Hello from tricu!" numbers = [1 2 3] --- Select greeting with Text, or numbers with List to inspect its elements. --- In source, list items use spaces; the playground's input box uses JSON. +-- Evaluate greeting with Text, or numbers with Bytes to display [1, 2, 3]. +-- Bytes requires a list of naturals in 0..255; use t source for other lists. +-- Lists use spaces, not commas: try identity [4 5 6]. -- 6. The result interpretation tells the playground how to read a tree. --- Use Text for a string, Natural number for a number, Tree graph for any tree. +-- Use Text for a string, Natural number for a number, or t source for any tree. -- Pure value observes the result; Browser IO interprets an IO action tree. -- The Conversation demo shows input, output and continuations. --- To change this program, copy it into Compiler, edit it and compile locally. --- Then run a definition repeatedly with different arguments. +-- Settings also offers structured arguments and stored-definition inspection. +-- Edits stay local; Restore original returns to the published source. -- For an application spanning lines, put the entire call in parentheses. --- Workspace programs can import libraries with !import module as NS. +-- Other demos import libraries by immutable manifest hash, shown in their headers. -- Next: Tree microscope shows how functions can inspect other program trees. diff --git a/ext/demo-site/demos/lexer.tri b/ext/demo-site/demos/lexer.tri @@ -1,14 +1,15 @@ -!import prelude * -!import parser * -!import lexer * -!import native_math as N +!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 * +!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d * +!import 816df1a32853750a1254112aff8ae8c55ca86bf70e809d226969ab1d43a6688b * +!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N !export scanWord !export scanWhitespace -- Positioned prefix scans, not whole-input parsers. The remainder begins -- at the first nonmatching character. Positions count source characters, -- not UTF-8 bytes or display columns: only LF advances the line. --- Native imports are pinned during preparation; browser source is read-only. +-- Edit a predicate below and evaluate scanWord "hello,world" to compare. +-- scanWhitespace accepts space, LF and tab, but deliberately not CR. report reply = (let payload = parserReplyPayload reply end = snd payload diff --git a/ext/demo-site/demos/microscope.tri b/ext/demo-site/demos/microscope.tri @@ -1,28 +1,27 @@ --- Structural operations on data OR program trees. No source evaluation. --- Direct three-constructor dispatch is intentional: ordered-pattern workers --- cost 3.9x the aggregate work on the retained 16-case screen. No lazy* thunks. -triage leaf stem fork = t (t leaf stem) fork -true = t t -false = t -both a b = triage false (ignored : b) (ignored ignored2 : b) a +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 as B +!export shape +!export size +!export same -shape tree = triage "Leaf" (child : "Stem") (left right : "Fork") tree +-- Inspect data OR compiled program trees, not source text. +-- Try shape (t t t), size (t t t), or same (t t) (t t). +-- Also try shape (x : x): functions are inspectable trees too. +-- triage dispatches directly on Leaf, Stem and Fork without visiting children. +-- Arithmetic and Booleans come from base; traversal is the subject of this demo. +shape tree = B.triage "Leaf" (child : "Stem") (left right : "Fork") tree --- Canonical numbers are least-significant-bit lists, not unary numbers. -succ n = (triage 1 (ignored : 0) - (bit rest : triage (t (t t) rest) (ignored : t t (succ rest)) (ignored ignored2 : 0) bit) - n) - -count tree acc = (triage - (succ acc) - (child : count child (succ acc)) - (left right : count right (count left (succ acc))) +-- Count every constructor occurrence, including repeated shared branches. +-- This is expanded tree size, not allocated nodes or source-code length. +count tree acc = (B.triage + (B.succ acc) + (child : count child (B.succ acc)) + (left right : count right (count left (B.succ acc))) tree) size tree = count tree 0 -same a b = (triage - (triage true (ignored : false) (ignored ignored2 : false) b) - (x : triage false (y : same x y) (ignored ignored2 : false) b) - (x y : triage false (ignored : false) (u v : both (same x u) (same y v)) b) +same a b = (B.triage + (B.triage B.true (ignored : B.false) (ignored ignored2 : B.false) b) + (x : B.triage B.false (y : same x y) (ignored ignored2 : B.false) b) + (x y : B.triage B.false (ignored : B.false) (u v : B.and? (same x u) (same y v)) b) a) diff --git a/ext/demo-site/demos/migration.tri b/ext/demo-site/demos/migration.tri @@ -1,15 +1,23 @@ +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 * +!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A +!export v1 +!export v2 + -- Archived profile v0: [name email]. v1: adds schemaVersion and displayName. -- v2: also supplies marketingOptIn=false; existing data is preserved. -- Select v1/v2 with the same input to compare the two target schemas. -- A migration receipt can record the input identity, executable hash/export, -- output identity and wire schema. Running this demo stays entirely local. --- Preparation closes practical-support.tri and selected base helpers into code. +-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean. +-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text. + +failure message = [["status" 0 "error"] ["message" 0 message]] -migrate version name email = case and? (text? name) (text? email) of +migrate version name email = case and? (A.hostString? name) (A.hostString? email) of ^true = (case version of - 1 = [(numberField "schemaVersion" 1) (stringField "displayName" name) (stringField "email" email)] - _ = [(numberField "schemaVersion" 2) (stringField "displayName" name) (stringField "email" email) - (boolField "marketingOptIn" false)]) + 1 = [["schemaVersion" 1 1] ["displayName" 0 name] ["email" 0 email]] + _ = [["schemaVersion" 1 2] ["displayName" 0 name] ["email" 0 email] + ["marketingOptIn" 2 false]]) _ = failure "Name and email must be scalar text." profile _ (t _) = failure "Expected a list." diff --git a/ext/demo-site/demos/parser.tri b/ext/demo-site/demos/parser.tri @@ -1,14 +1,14 @@ -!import prelude * -!import parser * -!import native_math as N +!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 * +!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d * +!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N !export parseNames !export parsePrefix -- Lowercase names separated by commas. Try "red,green", "red,,blue", -- "red," and "red green". A comma commits to another name. -- parseNames requires the entire input; parsePrefix exposes any remainder. --- These native imports are pinned at preparation time. Source is read-only --- here because browser draft compilation does not resolve native modules. +-- Edit the parser or labels below; valid edits compile locally. +-- Imports pin complete library interfaces, fetched only when compiling. nameParser = parserLabel "lowercase name" (parserSome (parserSatisfy (c : N.inRange c 97 122))) commaParser = parserThen (parserExpect 44) parserCommit namesPrefix = parserSepBy1 nameParser commaParser diff --git a/ext/demo-site/demos/practical-support.tri b/ext/demo-site/demos/practical-support.tri @@ -1,4 +1,5 @@ --- Shared standalone support, closed into the practical demo executables. +-- Explicit standalone-environment fixture for adapter/authentication tests. +-- Current examples declare native imports instead of receiving this profile. -- Preparation supplies existing binary arithmetic, canonical-natural and Boolean -- predicates from the accepted library; do not duplicate those algorithms here. true = t t diff --git a/ext/demo-site/demos/registration.tri b/ext/demo-site/demos/registration.tri @@ -1,25 +1,30 @@ +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 * +!import 3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55 as A +!export main + -- Registration validator: name, email, age, termsAccepted are separate arguments. -- Returns one field-specific message per input, plus an accepted Boolean. -- Name must be nonempty scalar text. Age must be a natural from 18 to 120. -- Email uses a deliberately small rule: nonempty text containing @ and a dot. -- Terms must be the canonical true Boolean. This is a teaching policy, not SMTP validation. -- Browser and server can pin this same executable instead of duplicating rules. --- Preparation closes practical-support.tri and selected base helpers into code. +-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean. +-- Base supplies arithmetic/Booleans; A.hostString? checks Unicode scalar text. -nameMessage name = case text? name of +nameMessage name = case A.hostString? name of ^true = (case name of [] = "Name is required." _ = "") _ = "Name must be scalar text." -emailMessage email = case text? email of +emailMessage email = case A.hostString? email of ^true = (case and? (contains? "@" email) (contains? "." email) of ^true = "" _ = "Email must contain @ and a dot.") _ = "Email must be scalar text." -ageMessage age = case natural? age of - ^true = (case and? (lessEq 18 age) (lessEq age 120) of +ageMessage age = case isNat? age of + ^true = (case and? (lte_? 18 age) (lte_? age 120) of ^true = "" _ = "Age must be from 18 to 120.") _ = "Age must be a canonical natural." @@ -28,8 +33,8 @@ termsMessage ^true = "" termsMessage _ = "Accept the terms." report name email age terms = [ - (boolField "accepted" (and? (equal? name "") (and? (equal? email "") (and? (equal? age "") (equal? terms ""))))) - (stringField "nameError" name) (stringField "emailError" email) - (stringField "ageError" age) (stringField "termsError" terms)] + ["accepted" 2 (and? (equal? name "") (and? (equal? email "") (and? (equal? age "") (equal? terms ""))))] + ["nameError" 0 name] ["emailError" 0 email] + ["ageError" 0 age] ["termsError" 0 terms]] main name email age terms = report (nameMessage name) (emailMessage email) (ageMessage age) (termsMessage terms) diff --git a/ext/demo-site/demos/rgb.tri b/ext/demo-site/demos/rgb.tri @@ -1,24 +1,15 @@ --- Exactly three canonical bytes: reject redundant high zero bits too. -true = t t -false = t -both left right = triage false (_ : right) (_ _ : right) left - --- Direct constructor dispatch in this per-bit hot loop avoids repeated pattern --- tests. A nonzero numeral's final bit must be true, not a redundant high zero. -triage leaf stem fork = t (t leaf stem) fork -bit? value = triage true (child : triage true (_ : false) (_ _ : false) child) (_ _ : false) value -bits? number budget = (triage true (_ : false) - (bit rest : triage false (_ : false) - (_ remaining : both (bit? bit) - (triage bit (_ : false) (_ _ : bits? rest remaining) rest)) - budget) - number) -byte? value = bits? value [t t t t t t t t] +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 * +!import 7a24af56a9ce9b947cadcafd3a9da127b1507275bfac62b9fa55e27490b176dc as Binary +!export main +-- Validate an RGB list using the library's canonical-byte predicate. +-- Try main [64 128 255], main [0 256 255], or main [0 1]. +-- Canonical encoding matters: redundant high zero bits are rejected too. +-- List-shape errors are separate from invalid channels; checks short-circuit. main (t _) = "Expected a list." main [_ | (t _)] = "Expected a list." main [_ | [_ | (t _)]] = "Expected a list." -main [r g b] = case both (byte? r) (both (byte? g) (byte? b)) of +main [r g b] = case and? (Binary.binaryByte? r) (and? (Binary.binaryByte? g) (Binary.binaryByte? b)) of ^true = "RGB triple accepted." _ = "A channel is not a canonical byte (0-255)." main _ = "Expected exactly three channels." diff --git a/ext/demo-site/demos/shipping.tri b/ext/demo-site/demos/shipping.tri @@ -1,32 +1,39 @@ +!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 * +!export v1 +!export v2 + -- Shipping policy: arguments are destination, cart subtotal in cents, grams. -- Destinations: domestic, regional, international. Grams: 1..5000. -- Select v1/v2 with the same cart: domestic free shipping changes from $75 to $100. -- Otherwise domestic costs $4.99/$5.99, regional $9.99, international $19.99. -- Packages above 1kg add $2.50. Subtotals are bounded to $10,000. -- The bundle hash + export pins the policy used to reproduce a quote later. --- Preparation closes practical-support.tri and selected base helpers into code. +-- Records use [fieldName tag value]: 0 = text, 1 = natural, 2 = Boolean. +-- Base supplies canonical-natural checks, arithmetic and Booleans. + +failure message = [["status" 0 "error"] ["message" 0 message]] baseRate 1 "domestic" = 499 baseRate _ "domestic" = 599 baseRate _ "regional" = 999 baseRate _ _ = 1999 -paidRate version zone grams = case lessEq grams 1000 of +paidRate version zone grams = case lte_? grams 1000 of ^true = baseRate version zone - _ = addBinary 250 (baseRate version zone) + _ = add 250 (baseRate version zone) freeThreshold 1 = 7500 freeThreshold _ = 10000 -amount version zone subtotal grams = case and? (equal? zone "domestic") (lessEq (freeThreshold version) subtotal) of +amount version zone subtotal grams = case and? (equal? zone "domestic") (lte_? (freeThreshold version) subtotal) of ^true = 0 _ = paidRate version zone grams -quote version zone subtotal grams = case and? (natural? subtotal) (natural? grams) of +quote version zone subtotal grams = case and? (isNat? subtotal) (isNat? grams) of ^true = (case or? (equal? zone "domestic") (or? (equal? zone "regional") (equal? zone "international")) of - ^true = (case and? (lessEq subtotal 1000000) (and? (lessEq 1 grams) (lessEq grams 5000)) of - ^true = [(stringField "status" "ok") (numberField "policyVersion" version) - (stringField "destination" zone) (numberField "shippingCents" (amount version zone subtotal grams))] + ^true = (case and? (lte_? subtotal 1000000) (and? (lte_? 1 grams) (lte_? grams 5000)) of + ^true = [["status" 0 "ok"] ["policyVersion" 1 version] + ["destination" 0 zone] ["shippingCents" 1 (amount version zone subtotal grams)]] _ = failure "Subtotal must be <=1000000 cents; grams must be 1..5000.") _ = failure "Unknown destination.") _ = failure "Subtotal and grams must be canonical natural numbers." diff --git a/ext/demo-site/dist/app.js b/ext/demo-site/dist/app.js @@ -1,3 +1,4 @@ +import { localModulesUI } from './local-modules-ui.js'; import { outputReveal } from './output-reveal.js'; import { syntaxEditor, tokenize, paintSyntax } from './syntax.js'; import { printLiteral } from './literal-input.js'; @@ -107,11 +108,39 @@ let automaticRun = false; let savedRun; let preferredExport; const traceRows = new Map(); +const localModules = localModulesUI(() => { + if (!draft) + return; + if (busy && operation !== 'compiling') + return; + editRevision++; + markPreviousResult(); + if (!busy) { + dispose(); + el('status').textContent = 'Changes pending'; + } + queueCompile(); +}); +const exportModuleButton = el('export-compiled-module'); +exportModuleButton.onclick = () => { + if (busy || !compiled || !draft || sourceEditor.value !== compiledSource || editRevision !== compiledRevision || !worker) + return; + cancelIdleCompile(); + operation = 'exporting'; + controls(true); + deadline.reset(Infinity); + clock(); + el('status').textContent = 'Exporting module'; + el('compiled-module-status').textContent = 'Observing public trees; Stop is available…'; + worker.postMessage({ type: 'export-module' }); +}; function pauseClock() { deadline.pause(); } function clock() { deadline.start(); } function runClock() { operation = 'running'; deadline.reset(Infinity); clock(); } function controls(working) { busy = working; + localModules.disable(busy); + exportModuleButton.disabled = busy || !draft || !compiled || sourceEditor.value !== compiledSource || editRevision !== compiledRevision; backendPicker.disabled = busy; programPicker.disabled = busy || entries.length === 0; versionPicker.disabled = busy; @@ -203,6 +232,8 @@ function clearOutput() { function finish(message, error = false, reason = 'failure') { if (error && reason === 'failure') message = operationFailure(operation, message); + if (operation === 'exporting' && draft) + el('compiled-module-status').textContent = message; if (operation === 'compiling' && reason === 'failure') { dispose(); el('status').textContent = 'Compilation failed'; @@ -628,6 +659,8 @@ function populatePrograms() { programPicker.disabled = false; } function showRelease(release) { + el('module-import-help').hidden = release === undefined; + el('module-import-source').textContent = release ? `!import ${release.manifest} as Library` : ''; el('release-info').textContent = release ? `${release.title} · ${release.name}@${release.version} · module ${release.manifest}` : 'No named release selected. Direct bundle hashes pin the whole file.'; } programPicker.onchange = () => { @@ -801,12 +834,12 @@ function compileDraft() { deadline.reset(Infinity); clock(); el('status').textContent = 'Compiling'; - el('compiler-stats').textContent = 'Loading pinned compiler and demo environment…'; + el('compiler-stats').textContent = 'Loading pinned compiler and source dependencies…'; const started = performance.now(); const activity = () => { el('compile-activity').hidden = false; el('compile-activity').textContent = `Compiling trees locally · ${Math.floor((performance.now() - started) / 1000)} seconds elapsed · Stop is available`; }; activity(); compilerTimer = setInterval(activity, 1000); - current.postMessage({ type: 'compile', source: snapshot.source, + current.postMessage({ type: 'compile', source: snapshot.source, localModules: localModules.inputs(), ...(!scratch && selected?.environment !== undefined ? { environment: selected.environment } : {}) }); } catch (error) { @@ -830,6 +863,23 @@ function draftWorker(snapshot) { if ((data.type === 'compiled' || data.type === 'error') && discardStale()) return; switch (data.type) { + case 'module-exported': { + idleDraft(); + const url = URL.createObjectURL(new Blob([new Uint8Array(data.bytes).buffer], { type: 'application/octet-stream' })); + const anchor = document.createElement('a'); + anchor.href = url; + anchor.download = `${data.hash}.arboricx`; + anchor.click(); + URL.revokeObjectURL(url); + el('compiled-module-status').textContent = `Exported compiled module. Manifest: ${data.manifest} · Bundle SHA-256: ${data.hash}. Open the downloaded file under Local modules to import it.`; + el('status').textContent = 'Compiled'; + break; + } + case 'module-export-error': + idleDraft(); + el('compiled-module-status').textContent = data.message; + el('status').textContent = 'Module export failed'; + break; case 'compiled': stopCompilerActivity(); pauseClock(); @@ -855,7 +905,7 @@ function draftWorker(snapshot) { if (data.state === 'running') { clock(); pending = undefined; - el('status').textContent = operation === 'compiling' ? 'Compiling' : 'Running'; + el('status').textContent = operation === 'compiling' ? 'Compiling' : operation === 'exporting' ? 'Exporting module' : 'Running'; } else { pauseClock(); @@ -968,7 +1018,10 @@ const examples = { }; for (const button of document.querySelectorAll('[data-compiler-example]')) button.onclick = () => { - const example = examples[button.dataset['compilerExample']]; + const math = packageReleases(releases, 'tricu-lib-native-math')[0]; + const example = button.dataset['compilerExample'] === 'module' && math + ? { name: 'answer', source: `!import ${math.manifest} as N\n!export answer\n\nanswer = N.add 40 2`, args: [], output: 'number', mode: 'pure' } + : examples[button.dataset['compilerExample']]; if (!example) return; chooseProgram(''); @@ -993,8 +1046,8 @@ for (const button of document.querySelectorAll('[data-compiler-example]')) presetExpression(example.name); controls(false); el('package-info').textContent = 'Scratch program · no published bundle selected.'; - el('release-info').textContent = ''; - el('source-label').textContent = 'Scratch program · contract helpers'; + showRelease(); + el('source-label').textContent = 'Scratch program · explicit modules or contract helpers'; el('status').textContent = 'Changes pending'; queueCompile(); }; diff --git a/ext/demo-site/dist/compiler.js b/ext/demo-site/dist/compiler.js @@ -13,7 +13,7 @@ export const COMPILER_COLLECTION = Object.freeze({ threshold: 250_000 }); export const SOURCE_LIMIT = 16_384; export function sourceText(source) { if (typeof source !== 'string' || !source.trim()) - throw new Error('Enter a standalone source unit'); + throw new Error('Enter a source unit or native module'); if (source.length > SOURCE_LIMIT * 2) throw new Error('Source limit exceeded'); let count = 0; @@ -50,7 +50,7 @@ export function compilerDiagnostic(graph, payload) { } // Decode only the result spine/names. Compiled program trees remain lazy handles. // Do not normalize/serialize them merely to populate an export selector. -export function compiledDefinitions(graph, result) { +export function compiledDefinitions(graph, result, allowEmpty = false) { const [tag, payload] = graph.pair(result, 'compiler result'); const flag = graph.observe(tag).node; if (flag.kind === 'leaf') @@ -66,7 +66,7 @@ export function compiledDefinitions(graph, result) { throw new Error('Empty/duplicate compiled definition name'); exports.set(name, program); } - if (!exports.size) + if (!exports.size && !allowEmpty) throw new Error('Source unit produced no definitions'); return exports; } diff --git a/ext/demo-site/dist/haskell-session.js b/ext/demo-site/dist/haskell-session.js @@ -1,10 +1,10 @@ +import { moduleSnapshot } from './module-bundle.js'; import { isTreeResult, treeResult } from './tree-result.js'; import { expressionUnit, expressionDiagnostic } from './expression.js'; // Backend-private protocol mapping. No WASM pointer, Haskell heap checkpoint or // fabricated graph statistic crosses into the shared site protocol. import { compilerDescriptor } from './compiler.js'; import { fetchBytes } from './bundle.js'; -import { environmentProfile } from './packages.js'; export class HaskellSession { client; linearMemoryBytes = 0; @@ -40,21 +40,17 @@ export class HaskellSession { } async json(message) { return JSON.parse((await this.request(message)).text); } async load(bytes, hash) { this.names = await this.json({ type: 'load', bytes: new Uint8Array(bytes).buffer, hash }); } - async compile(source, profileName) { - let environment; - if (profileName !== undefined) { - const bytes = await fetchBytes(new URL('../environments.json', import.meta.url), 32768); - const selected = environmentProfile(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)), profileName); - if (selected.compiler !== this.compilerHash) - throw new Error('Demo environment/compiler pin mismatch'); - environment = selected.profile ? { - bytes: new Uint8Array(await fetchBytes(new URL(`/_arboricx/bundle/hash/${selected.profile.hash}`, import.meta.url))).buffer, - hash: selected.profile.hash, names: selected.profile.names, - } : null; - } - const reply = await this.request({ type: 'compile', source, ...(environment === undefined ? {} : { environment }) }); - this.names = reply.text.trimEnd().split('\n').filter(Boolean); - return this.names; + async compile(source, profileName, localModules = []) { + this.names = []; + const reply = await this.request({ type: 'compile', source, localModules, base: new URL('../', import.meta.url).href, + ...(profileName === undefined ? {} : { profileName }) }); + const names = reply.text.trimEnd().split('\n').filter(Boolean); + this.names = reply.scopeNames ?? names; + return names; + } + async exportModule() { + const value = await this.json({ type: 'module-snapshot' }); + return moduleSnapshot(value.names, value.snapshot); } async run(name, args, output, mode, host) { return this.execute({ type: mode === 'pure' ? 'evaluate' : 'io-start', name, arguments: args, output }, output, mode, host); diff --git a/ext/demo-site/dist/local-module-worker.js b/ext/demo-site/dist/local-module-worker.js @@ -0,0 +1,5 @@ +import { validateLocalModule } from './local-modules.js'; +const scope = globalThis; +scope.onmessage = ({ data }) => { + void validateLocalModule(data).then(module => scope.postMessage({ module }), error => scope.postMessage({ error: String(error) })); +}; diff --git a/ext/demo-site/dist/local-modules-ui.js b/ext/demo-site/dist/local-modules-ui.js @@ -0,0 +1,96 @@ +import { BUNDLE_LIMIT } from './bundle.js'; +import { LOCAL_MODULE_BYTES, LOCAL_MODULE_COUNT } from './local-modules.js'; +// Hold local module files in page memory until removal or page departure. +export function localModulesUI(changed) { + const input = document.getElementById('local-module-file'); + const list = document.getElementById('local-module-list'); + const status = document.getElementById('local-module-status'); + const cancel = document.getElementById('cancel-local-module'); + const modules = new Map(); + let busy = false, checking = false, abort; + const render = () => { + input.disabled = busy || checking; + cancel.hidden = !checking; + list.replaceChildren(); + for (const [manifest, { label, module }] of modules) { + const row = document.createElement('li'), title = document.createElement('p'); + title.textContent = `${label} · ${module.names.length} export(s) · ${module.bytes.byteLength.toLocaleString()} bytes`; + const code = document.createElement('code'); + code.textContent = `!import ${manifest} as Local`; + const details = document.createElement('details'), summary = document.createElement('summary'), names = document.createElement('p'); + summary.textContent = 'Exports and bundle hash'; + names.textContent = `${module.names.join(', ')}\nBundle SHA-256: ${module.hash}`; + details.append(summary, names); + const copy = document.createElement('button'); + copy.textContent = 'Copy import'; + copy.onclick = () => { void (async () => { try { + await navigator.clipboard.writeText(code.textContent); + status.textContent = 'Import copied.'; + } + catch { + status.textContent = code.textContent; + } })(); }; + const remove = document.createElement('button'); + remove.textContent = 'Remove'; + remove.dataset['removeModule'] = manifest; + remove.disabled = busy || checking; + remove.onclick = () => { modules.delete(manifest); render(); status.textContent = 'Local module removed. Draft imports will be resolved again.'; changed(); }; + row.append(title, code, details, copy, remove); + list.append(row); + } + }; + cancel.onclick = () => abort?.(); + input.onchange = () => { + const file = input.files?.[0]; + input.value = ''; + if (!file || busy || checking) + return; + if (!file.size || file.size > BUNDLE_LIMIT) { + status.textContent = 'Choose a nonempty .arboricx file of at most 16 MiB.'; + return; + } + checking = true; + render(); + status.textContent = 'Checking module locally…'; + void (async () => { + let worker, active = true; + let timer; + try { + const current = new Worker(new URL('./local-module-worker.js', import.meta.url), { type: 'module' }); + worker = current; + const module = await new Promise((resolve, reject) => { + abort = () => reject(new Error('Local file check cancelled.')); + timer = setTimeout(() => reject(new Error('Local file check timed out.')), 60_000); + current.onmessage = ({ data }) => data.module ? resolve(data.module) : reject(new Error(data.error ?? 'Invalid local module')); + current.onerror = event => { event.preventDefault(); reject(new Error(event.message || 'Local file check failed')); }; + void file.arrayBuffer().then(bytes => { if (active) + current.postMessage(new Uint8Array(bytes)); }).catch(reject); + }); + if (modules.has(module.manifest)) { + status.textContent = 'This module manifest is already available locally.'; + return; + } + const total = [...modules.values()].reduce((n, item) => n + item.module.bytes.byteLength, module.bytes.byteLength); + if (modules.size >= LOCAL_MODULE_COUNT || total > LOCAL_MODULE_BYTES) + throw new Error('Local collection limit: 32 modules / 64 MiB. Remove a module first.'); + modules.set(module.manifest, { label: file.name.slice(0, 256), module }); + status.textContent = 'Available locally by manifest hash.'; + changed(); + } + catch (error) { + status.textContent = String(error); + } + finally { + active = false; + clearTimeout(timer); + worker?.terminate(); + abort = undefined; + checking = false; + render(); + } + })(); + }; + render(); + return { inputs: () => [...modules.values()].map(({ module }) => ({ manifest: module.manifest, bytes: module.bytes })), disable: value => { busy = value; input.disabled = busy || checking; for (const button of list.querySelectorAll('[data-remove-module]')) + button.disabled = busy || checking; } }; +} diff --git a/ext/demo-site/dist/local-modules.js b/ext/demo-site/dist/local-modules.js @@ -0,0 +1,31 @@ +import { BUNDLE_LIMIT, decodeBundle, sha256 } from './bundle.js'; +import { moduleHash, moduleIdentity } from './module-identity.js'; +export const LOCAL_MODULE_COUNT = 32, LOCAL_MODULE_BYTES = 64 * 1024 * 1024; +export async function validateLocalModule(input) { + if (!(input instanceof Uint8Array) || !input.byteLength || input.byteLength > BUNDLE_LIMIT) + throw new Error('Local module must be at most 16 MiB'); + const bytes = new Uint8Array(input), bundle = decodeBundle(bytes); + return { bytes, manifest: await moduleIdentity(bundle), hash: await sha256(bytes), names: bundle.exports.map(e => e.name) }; +} +// Copy at the async boundary; verify supplied identities against these bytes. +export function localModuleInputs(input = []) { + if (!Array.isArray(input) || input.length > LOCAL_MODULE_COUNT) + throw new Error('Local module count limit exceeded'); + let size = 0; + const seen = new Set(); + return input.map((entry) => { + if (!entry || typeof entry !== 'object') + throw new Error('Invalid local module'); + const { manifest, bytes } = entry; + moduleHash(manifest); + if (seen.has(manifest)) + throw new Error('Duplicate local module manifest'); + seen.add(manifest); + if (!(bytes instanceof Uint8Array) || !bytes.byteLength || bytes.byteLength > BUNDLE_LIMIT) + throw new Error('Local module byte limit exceeded'); + size += bytes.byteLength; + if (size > LOCAL_MODULE_BYTES) + throw new Error('Local module collection exceeds 64 MiB'); + return { manifest, bytes: new Uint8Array(bytes) }; + }); +} diff --git a/ext/demo-site/dist/module-bundle.js b/ext/demo-site/dist/module-bundle.js @@ -0,0 +1,96 @@ +// Explicit publication boundary: snapshots observe finite constructor trees. +// Canonical indexing preserves DAG sharing. +import { BUNDLE_LIMIT, decodeBundle } from './bundle.js'; +import { snapshotBundle } from './tree-result.js'; +const encoder = new TextEncoder(); +const join = (parts) => { + const length = parts.reduce((n, p) => n + p.length, 0); + if (length > BUNDLE_LIMIT) + throw new Error('Module bundle exceeds 16 MiB'); + const out = new Uint8Array(length); + let at = 0; + for (const part of parts) { + out.set(part, at); + at += part.length; + } + return out; +}; +function word(n, size = 4) { + const bytes = new Uint8Array(size), view = new DataView(bytes.buffer); + if (size === 8) + view.setBigUint64(0, BigInt(n)); + else if (size === 2) + view.setUint16(0, n); + else + view.setUint32(0, n); + return bytes; +} +const string = (s) => { const bytes = encoder.encode(s); return join([word(bytes.length), bytes]); }; +export function encodeModule(bundle) { + if (!bundle.exports.length || bundle.exports.length > 4096) + throw new Error('Invalid module export count'); + const mapped = new Map(), interned = new Map(), records = []; + for (const entry of bundle.exports) { + if (!/^[A-Za-z_][A-Za-z0-9_?$%'.-]*$/u.test(entry.name) || encoder.encode(entry.name).length > 512) + throw new Error('Invalid module export name'); + const stack = [[entry.root, false]]; + while (stack.length) { + const [id, leave] = stack.pop(); + if (mapped.has(id)) + continue; + const node = bundle.nodes[id]; + if (!node) + throw new Error('Missing module node'); + const children = node.kind === 'leaf' ? [] : node.kind === 'stem' ? [node.child] : [node.left, node.right]; + if (children.some(c => c < 0 || c >= id)) + throw new Error('Invalid module edge'); + if (!leave) { + stack.push([id, true]); + for (const c of [...children].reverse()) + stack.push([c, false]); + } + else { + const row = children.map(c => mapped.get(c)), key = row.length + ':' + row.join(','); + let index = interned.get(key); + if (index === undefined) { + index = records.length; + interned.set(key, index); + records.push(row); + } + if (records.length > 100_000) + throw new Error('Module node limit exceeded'); + mapped.set(id, index); + } + } + } + const manifest = join([encoder.encode('ARBMNFST'), word(1, 2), word(1, 2), + ...['arboricx.bundle.manifest.v1', 'tree-calculus-executable-object', 'tree-calculus.v1', 'indexed', + 'arboricx.indexed.node.v1', 'arboricx.indexed.payload.v1', 'tree-calculus.v1', 'normal-order', 'arboricx.abi.tree.v1'].map(string), + word(0), new Uint8Array([0]), word(bundle.exports.length), + ...bundle.exports.flatMap((e, i) => [word(mapped.get(e.root)), string(i ? 'root' : 'default')]), + word(bundle.exports.length), ...bundle.exports.flatMap(e => [string(e.name), word(mapped.get(e.root)), string('term'), string('arboricx.abi.tree.v1')]), + word(0), word(0)]); + const nodes = join([word(records.length, 8), ...records.map(row => { + const payload = join([new Uint8Array([row.length]), ...row.map(n => word(n))]); + return join([word(payload.length), payload]); + })]); + const section = (type, at, size) => join([word(type), word(1, 2), word(1, 2), word(0), word(at, 8), word(size, 8), word(0)]); + const bytes = join([encoder.encode('ARBORICX'), word(1, 2), word(0, 2), word(2), word(0, 8), word(32, 8), + section(1, 96, manifest.length), section(2, 96 + manifest.length, nodes.length), manifest, nodes]); + decodeBundle(bytes); // Independent reader enforces the actual portable profile. + return bytes; +} +export function moduleSnapshot(names, snapshot) { + const bundle = snapshotBundle(snapshot); + let spine = bundle.roots[0]; + bundle.exports = names.map(name => { + const cell = bundle.nodes[spine]; + if (cell?.kind !== 'fork') + throw new Error('Invalid module snapshot spine'); + spine = cell.right; + return { name, root: cell.left, kind: 'term', abi: 'arboricx.abi.tree.v1' }; + }); + if (bundle.nodes[spine]?.kind !== 'leaf') + throw new Error('Invalid module snapshot tail'); + return encodeModule(bundle); +} diff --git a/ext/demo-site/dist/module-identity.js b/ext/demo-site/dist/module-identity.js @@ -0,0 +1,81 @@ +// Native indexed import identity (ContentStore.Bundle / Wire.extractBundleRoot). +// Hash stored DAG records in left-before-right physical-edge order. +import { bundleHash, sha256 } from './bundle.js'; +export function moduleHash(value) { return bundleHash(value); } +const utf8 = new TextEncoder(); +function join(parts) { + const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0)); + let at = 0; + for (const p of parts) { + out.set(p, at); + at += p.length; + } + return out; +} +function word(n, size = 4) { + const out = new Uint8Array(size), view = new DataView(out.buffer); + if (size === 8) + view.setBigUint64(0, BigInt(n)); + else if (size === 2) + view.setUint16(0, n); + else + view.setUint32(0, n); + return out; +} +const string = (s) => { const b = utf8.encode(s); return join([word(b.length), b]); }; +export function indexedObject(bundle, root) { + const ids = new Map(), rows = [], stack = [[root, false]]; + while (stack.length) { + const [id, leave] = stack.pop(); + if (ids.has(id)) + continue; + const node = bundle.nodes[id]; + if (!node) + throw new Error('Missing indexed node'); + const children = node.kind === 'leaf' ? [] : node.kind === 'stem' ? [node.child] : [node.left, node.right]; + if (children.some(c => c >= id || c < 0)) + throw new Error('Invalid indexed edge'); + if (!leave) { + stack.push([id, true]); + for (const c of children.reverse()) + stack.push([c, false]); + } + else { + const payload = join([new Uint8Array([children.length]), ...children.map(c => word(ids.get(c)))]); + ids.set(id, rows.length); + rows.push(join([word(payload.length), payload])); + } + } + const index = ids.get(root); + const manifest = join([ + utf8.encode('ARBMNFST'), word(1, 2), word(1, 2), + ...['arboricx.bundle.manifest.v1', 'tree-calculus-executable-object', 'tree-calculus.v1', 'indexed', + 'arboricx.indexed.node.v1', 'arboricx.indexed.payload.v1', 'tree-calculus.v1', 'normal-order', 'arboricx.abi.tree.v1'].map(string), + word(0), new Uint8Array([0]), word(1), word(index), string('default'), + word(1), string('root'), word(index), string('term'), string('arboricx.abi.tree.v1'), + word(1), word(5, 2), string('arboricx'), word(0), + ]); + const nodes = join([word(rows.length, 8), ...rows]); + const section = (type, at, size) => join([ + word(type), word(1, 2), word(1, 2), word(0, 2), word(0, 2), word(at, 8), word(size, 8), word(0), + ]); + return join([utf8.encode('ARBORICX'), word(1, 2), word(0, 2), word(2), word(0, 8), word(32, 8), + section(1, 96, manifest.length), section(2, 96 + manifest.length, nodes.length), manifest, nodes]); +} +export async function moduleIdentity(bundle) { + if (!bundle.exports.length || bundle.exports.some(e => !/^[A-Za-z_][A-Za-z0-9_?$%'.-]*$/u.test(e.name))) { + throw new Error('Package requires a nonempty native module interface'); + } + const hashes = new Map(); + let manifest = 'arboricx.module-manifest.v1\n'; + const escape = (s) => s.replace(/%/g, '%25').replace(/\t/g, '%09').replace(/\n/g, '%0A').replace(/\r/g, '%0D'); + for (const e of bundle.exports) { + let hash = hashes.get(e.root); + if (!hash) { + hash = await sha256(join([utf8.encode('arboricx.indexed-tree.v1\0'), indexedObject(bundle, e.root)])); + hashes.set(e.root, hash); + } + manifest += `export\t${escape(e.name)}\tarboricx.indexed-tree.v1\t${hash}\t${e.abi}\n`; + } + return moduleHash(await sha256(utf8.encode('arboricx.module-manifest.v1\0' + manifest))); +} diff --git a/ext/demo-site/dist/module-resolver.js b/ext/demo-site/dist/module-resolver.js @@ -0,0 +1,13 @@ +// Resolve indexed immutable manifests and verify their transport and module pins. +import { fetchBundle } from './bundle.js'; +import { moduleHash, moduleIdentity } from './module-identity.js'; +export async function fetchModule(base, reference, releases) { + const manifest = moduleHash(reference); + const release = releases.find(r => r.manifest === manifest); + if (!release) + throw new Error(`Unknown module manifest ${manifest}`); + const bundle = await fetchBundle(new URL(`/_arboricx/bundle/hash/${release.hash}`, base), release.hash); + if (await moduleIdentity(bundle) !== manifest) + throw new Error('Module manifest mismatch'); + return bundle; +} diff --git a/ext/demo-site/dist/module-stage.js b/ext/demo-site/dist/module-stage.js @@ -0,0 +1,87 @@ +import { readList, readText, text } from './codecs.js'; +import { compilerDiagnostic, SOURCE_LIMIT } from './compiler.js'; +import { fetchBytes, decodeBundle } from './bundle.js'; +import { packageIndex } from './packages.js'; +import { localModuleInputs, validateLocalModule } from './local-modules.js'; +import { fetchModule } from './module-resolver.js'; +export function stageModule(graph, library, source) { + const call = (name, argument) => { + const f = library.get('source_module.' + name); + if (f === undefined) + throw new Error('Missing native module compiler helper'); + return graph.apply(f, [argument]); + }; + const value = (result, diagnostic = false) => { + const [tag, payload] = graph.pair(result), flag = graph.observe(tag).node; + if (flag.kind === 'leaf') + throw new Error(diagnostic ? compilerDiagnostic(graph, payload) : readText(graph, graph.pair(payload)[0], 512)); + if (flag.kind !== 'stem' || graph.observe(flag.child).node.kind !== 'leaf') + throw new Error('Invalid native module result'); + return graph.pair(payload)[0]; + }; + const [edges, rest] = graph.pair(value(call('sourceModuleHeaderStage', text(graph, source, SOURCE_LIMIT)), true)); + if (readList(graph, edges, SOURCE_LIMIT).length) + throw new Error('Browser modules require manifest hashes; workspace and build-only sources are unavailable'); + const [uses, tail] = graph.pair(rest), [exports, body] = graph.pair(tail); + const shapes = (rows, helper) => readList(graph, rows, SOURCE_LIMIT).map(row => { + const [a, b] = graph.pair(value(call(helper, row))); + return [readText(graph, a, 128), readText(graph, b, 128)]; + }); + const imports = shapes(uses, 'sourceModuleUseShape'), selected = shapes(exports, 'sourceModuleExportShape'); + return { body: readText(graph, body, SOURCE_LIMIT), imports, exports: selected, native: !!(imports.length || selected.length) }; +} +export async function moduleDependencies(base, stage, local = []) { + const refs = [...new Set([...stage.imports.map(i => i[0]), ...stage.exports.filter(e => e[0] === 'from').map(e => e[1])])]; + const result = new Map(); + if (!refs.length) + return result; + const available = new Map(localModuleInputs(local).map(entry => [entry.manifest, entry])); + let index; + for (const ref of refs) { + const entry = available.get(ref); + if (entry) { + const checked = await validateLocalModule(entry.bytes); + if (checked.manifest !== ref) + throw new Error('Local module manifest mismatch'); + result.set(ref, decodeBundle(checked.bytes)); + } + else { + index ??= packageIndex(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(await fetchBytes(new URL('packages.json', base), 2_097_152)))); + result.set(ref, await fetchModule(base, ref, index)); + } + } + return result; +} +// Projection of already native-parsed export requests onto backend-owned trees. +// Keep executable trees as backend-owned handles during interface selection. +export function selectModuleExports(stage, locals, modules) { + const selected = new Map(); + const add = (name, tree) => { + if (selected.has(name)) + throw new Error('duplicate export'); + if (selected.size >= 4096) + throw new Error('Module export limit exceeded'); + selected.set(name, tree); + }; + for (const [name, ref] of stage.exports) { + if (name === 'from') { + const values = modules.get(ref); + if (!values) + throw new Error('Missing re-export dependency'); + for (const [key, value] of values) + add(key, value); + } + else if (name === '*') { + for (const [key, value] of locals) + add(key, value); + } + else { + if (!locals.has(name)) + throw new Error('undeclared local export'); + add(name, locals.get(name)); + } + } + if (!selected.size) + throw new Error('module requires an export'); + return selected; +} diff --git a/ext/demo-site/dist/wasm-worker.js b/ext/demo-site/dist/wasm-worker.js @@ -1,3 +1,4 @@ +import { localModuleInputs, validateLocalModule } from './local-modules.js'; import { resumeValue } from './io.js'; import { createRuntimeSession } from './runtime-session.js'; const selectedBackend = new URL(globalThis.location.href).searchParams.get('backend'); @@ -58,9 +59,23 @@ scope.onmessage = ({ data }) => { running(); const start = performance.now(); session = await createRuntimeSession(selectedBackend, true); - const names = await session.compile(source, profile); + const names = await session.compile(source, profile, localModuleInputs(m['localModules'])); send({ type: 'compiled', names, stats: session.stats(), milliseconds: performance.now() - start }); } + else if (m['type'] === 'export-module') { + if (!session || stored) + throw new Error('Compile a draft first'); + running(); + try { + const module = await validateLocalModule(await session.exportModule()); + send({ type: 'module-exported', bytes: module.bytes, hash: module.hash, manifest: module.manifest }); + } + catch (e) { + if (session.disposed) + throw e; + send({ type: 'module-export-error', message: String(e) }); + } + } else if (m['type'] === 'run') { if (!session) throw new Error('Load or compile first'); diff --git a/ext/demo-site/environments.json b/ext/demo-site/environments.json @@ -26,7 +26,7 @@ "boolField", "failure" ], - "sourceSha256": "267dd96923b17f67cdce383cf464a11c4d379c8a893f05e8ea273d515283f0a2" + "sourceSha256": "1b5358c15eaabc74273a0d5395d12793137b257019b2c07d03818852505068bb" } } } diff --git a/ext/demo-site/index.html b/ext/demo-site/index.html @@ -45,7 +45,7 @@ <div><label for="output-type">Interpretation</label><select id="output-type"><option value="tricu">tricu · t source</option><option value="triangle">△ source</option><option value="dag">DAG · shared △</option><option value="ternary">Ternary</option><option value="string">Text</option><option value="number">Natural number</option><option value="bool">Boolean</option><option value="bytes">Bytes</option><option value="record">Scalar record</option></select></div> <div><label for="mode">Execution</label><select id="mode"><option value="pure">Pure value</option><option value="io">Text / line IO</option></select></div> </div> - <div id="expression-inputs"><label for="expression-editor">Expression <span>· use the loaded definitions</span></label><textarea id="expression-editor" rows="3" maxlength="32768" spellcheck="false" autocapitalize="off" autocorrect="off" aria-describedby="expression-help"></textarea><p id="expression-help" class="hint">Literals, applications and local bindings. No implicit prelude or browser module imports.</p></div> + <div id="expression-inputs"><label for="expression-editor">Expression <span>· use the loaded definitions</span></label><textarea id="expression-editor" rows="3" maxlength="32768" spellcheck="false" autocapitalize="off" autocorrect="off" aria-describedby="expression-help"></textarea><p id="expression-help" class="hint">Use literals, applications and bindings from the current scope. Declare imports in the source editor.</p></div> <div id="guided-inputs" hidden><div class="argument-heading"><h3>Structured arguments</h3><button id="add-argument">Add argument</button></div><div id="argument-fields"></div></div> <p id="draft-run-note" class="hint" role="status" hidden></p> <div class="evaluation-actions"><button id="run" class="primary" disabled>Evaluate</button><button id="stop-run" disabled>Stop</button></div> @@ -64,7 +64,7 @@ <section><h3>Execution</h3> <label class="check"><input id="use-guided-inputs" type="checkbox"> Use structured arguments</label> <label class="check"><input id="step-mode" type="checkbox"> Pause before each IO action</label> - <p class="hint">Stop terminates active work. Compilation never runs the program.</p> + <p class="hint">Stop terminates active work. Evaluate runs the compiled program.</p> <button id="reset">Clear output</button><button id="share" disabled>Copy published selection link</button> </section> <details><summary>Structured argument encoding</summary><p class="hint">One literal per field: 42, "hello", [1 2 3], or (t t t). No fields means no arguments. Use raw JSON for exact wire kinds or deeply nested trees.</p><label class="check"><input id="raw-arguments" type="checkbox"> Raw typed JSON</label><label class="sr-only" for="arguments">Typed argument array</label><textarea id="arguments" rows="5" maxlength="16000" spellcheck="false" hidden>[]</textarea></details> @@ -72,11 +72,20 @@ <div id="package-toolbar" hidden><div id="program-release" hidden><label for="package-version">Version</label><div class="input-row"><select id="package-version"></select><button id="load-release" disabled>Load</button></div></div> <form id="program-hash" hidden><label for="bundle-hash">Bundle SHA-256</label><div class="input-row"><input id="bundle-hash" maxlength="64" spellcheck="false" autocomplete="off" aria-describedby="bundle-hash-help"><button id="load">Load</button></div></form> <button id="download-bundle" disabled>Download .arboricx</button></div> - <p id="bundle-hash-help" class="hint" hidden>Load a published executable by its exact 64-character hash.</p><p id="bundle-download-status" class="hint" role="status"></p><p id="release-info" class="hint"></p><p id="package-info" class="hint">Verifying package…</p> + <p id="bundle-hash-help" class="hint" hidden>Load a published executable by its exact 64-character hash.</p><p id="bundle-download-status" class="hint" role="status"></p><p id="release-info" class="hint"></p><p id="module-import-help" class="hint" hidden>Import in source: <code id="module-import-source"></code> (then declare <code>!export</code>).</p><p id="package-info" class="hint">Verifying package…</p> </section> - <section><h3>Scratch examples</h3><p class="hint">Standalone source with contract helpers. Choosing an example replaces the editor contents.</p><div class="demo-picker"><button data-compiler-example="identity">Identity</button><button data-compiler-example="contracts">Checked identity</button><button data-compiler-example="pair">Pair</button><button data-compiler-example="definitions">Definitions</button><button data-compiler-example="input">Line input</button></div></section> - <section><h3>Runtime / compilation</h3><button id="compile" disabled hidden>Compile now</button><p id="compiler-stats" class="hint">Compilation starts after an editing pause.</p><p class="hint">Source stays in this page only. Copy it before leaving; there is no autosave.</p></section> - <details><summary>Output boundaries</summary><p class="hint">Tree results demand a complete finite tree, up to 100,000 observed nodes. Expanded files allow 32 MiB; DAG files allow 128 MiB. Incomplete snapshots are refused, never saved as complete trees. Stored definitions are read without evaluation. Stop remains available during computation; browser memory is finite.</p></details> + <section id="local-modules"><h3>Local modules</h3> + <p class="hint">Open a .arboricx file locally and import it by manifest hash. Reloading clears the collection. Limits: 16 MiB/file, 32 modules / 64 MiB total.</p> + <label for="local-module-file">Open local module</label><input id="local-module-file" type="file" accept=".arboricx"> + <button id="cancel-local-module" hidden>Cancel file check</button> + <p id="local-module-status" class="hint" role="status"></p><ul id="local-module-list"></ul> + <button id="export-compiled-module" disabled>Export compiled module</button> + <p class="hint">Exports the current draft's public interface as executable trees. Export may take time or diverge; Stop remains available. Exports must be complete and within size limits.</p> + <p id="compiled-module-status" class="hint" role="status"></p> + </section> + <section><h3>Scratch examples</h3><p class="hint">Standalone source with contract helpers, or native modules with explicit imports. Choosing an example replaces the editor contents.</p><div class="demo-picker"><button data-compiler-example="identity">Identity</button><button data-compiler-example="contracts">Checked identity</button><button data-compiler-example="pair">Pair</button><button data-compiler-example="definitions">Definitions</button><button data-compiler-example="input">Line input</button><button data-compiler-example="module">Module imports</button></div></section> + <section><h3>Runtime / compilation</h3><button id="compile" disabled hidden>Compile now</button><p id="compiler-stats" class="hint">Compilation starts after an editing pause.</p><p class="hint">Source stays in this page. Copy it before leaving.</p></section> + <details><summary>Output boundaries</summary><p class="hint">Tree results demand a complete finite tree, up to 100,000 observed nodes. Expanded files allow 32 MiB; DAG files allow 128 MiB. Export requires a complete snapshot. Stored definitions use the original bundle records. Stop remains available during computation; browser memory is finite.</p></details> </aside> </div> </section> diff --git a/ext/demo-site/lexer-demo.json b/ext/demo-site/lexer-demo.json @@ -1,9 +1,10 @@ { "id": "lexer", + "source": "!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 *\n!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d *\n!import 816df1a32853750a1254112aff8ae8c55ca86bf70e809d226969ab1d43a6688b *\n!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N\n!export scanWord\n!export scanWhitespace\n\n-- Positioned prefix scans, not whole-input parsers. The remainder begins\n-- at the first nonmatching character. Positions count source characters,\n-- not UTF-8 bytes or display columns: only LF advances the line.\n-- Edit a predicate below and evaluate scanWord \"hello,world\" to compare.\n-- scanWhitespace accepts space, LF and tab, but deliberately not CR.\nreport reply = (let\n payload = parserReplyPayload reply\n end = snd payload\n in [\n [\"matched\" 0 (fst payload)]\n [\"remaining\" 0 (parserReplyRest reply)]\n [\"line\" 1 (lexerPositionLine end)]\n [\"column\" 1 (lexerPositionColumn end)]\n [\"offset\" 1 (lexerPositionOffset end)]\n [\"consumed\" 2 (parserReplyConsumed reply)]])\n\nscan predicate text = report (lexerMapScan reverse\n (lexerScanWhile text lexerStart [] predicate (state character : pair character state)))\nscanWord text = scan (character : N.inRange character 97 122) text\nscanWhitespace text = scan (character : or? (equal? character 32)\n (or? (equal? character 9) (equal? character 10))) text\n", "hash": "e756a481b3056a2e76f50316ccf77bfab8b15727b7bec899580c2eb919e668b2", "mode": "pure", "compilerSha256": "d70de875988dfa309f2c167992928866f88b08af351918b8c7b5d88c541c6e94", - "sourceSha256": "5478169b100e087b8f8862418a2cd5d0e593edcc299a122b762842483f4525e0", + "sourceSha256": "ec68af4102c16ef56be01e78a3288bea57af71ca57ab35374a0d12005b5a10a1", "haskellCases": [ { "export": "scanWord", diff --git a/ext/demo-site/packages.json b/ext/demo-site/packages.json @@ -907,6 +907,436 @@ "manifest": "ed99e054e9c862668e165f458d3afcdc56279f766eea7a3886d440aea7252b63", "title": "Located scans: matched prefix, remainder and character positions", "demo": "lexer" + }, + { + "name": "tricu-lib-arboricx", + "version": "0.1.0", + "manifest": "3f70d95cf1bae0928ee89acd2a9e0cdd8287796efae32a9f08d33e3dd0149c55", + "hash": "40dfb23da91b505ea4586bbfea46a7374d299bb747796f18428de7da43fa7315", + "title": "lib/arboricx/arboricx.tri" + }, + { + "name": "tricu-lib-arboricx-common", + "version": "0.1.0", + "manifest": "0d779adef29b51ee875bf2f46ec03bef30ec48d200e7e05c9e20bd90b28ac4a4", + "hash": "2c8f29c5e1a96eac7b6d57f6dad02f7adbfca1da93742f48c2aff3534c378284", + "title": "lib/arboricx/common.tri" + }, + { + "name": "tricu-lib-arboricx-dispatch", + "version": "0.1.0", + "manifest": "eda078ba018de68718b2b7aa2d790578ac079cf98c963a78f7fcae5178fd2c19", + "hash": "7fbcf00a8412785c5c61b61c21c89d00d2597953b040faa02e6e811677b37578", + "title": "lib/arboricx/dispatch.tri" + }, + { + "name": "tricu-lib-arboricx-manifest", + "version": "0.1.0", + "manifest": "2a8a2b591dfc4192b8ded6e2ea75e94f6ff41183636f6024b6d5eb590ec8d2aa", + "hash": "718c96fe7ab33504ece9c041f7a93dddf15b281f8dfceba84291a349e260b15f", + "title": "lib/arboricx/manifest.tri" + }, + { + "name": "tricu-lib-arboricx-nodes", + "version": "0.1.0", + "manifest": "d158e4ebe9fd6cfb752023bbe031614b190b9eab79e9680875a1fc55dc481a23", + "hash": "84a7479abac8663864a5615e5c0be69b6bb64530a904ab0da274bbf68b682b01", + "title": "lib/arboricx/nodes.tri" + }, + { + "name": "tricu-lib-arboricx-server", + "version": "0.1.0", + "manifest": "451e24aeec39ff1295c0c735897dcefd34b9219ef72a8b0c619b678373afcfa1", + "hash": "c8bc5c1ebeff9189d64ffd23554026d6f39aed92e2b25a4fa0935a0d25b99608", + "title": "lib/arboricx/server.tri" + }, + { + "name": "tricu-lib-base", + "version": "0.1.0", + "manifest": "bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81", + "hash": "ed931d1cf10921f414c7fb2e21c4ab40509d548b56ca1db1327586d90cdf6f0a", + "title": "lib/base.tri" + }, + { + "name": "tricu-lib-binary", + "version": "0.1.0", + "manifest": "7a24af56a9ce9b947cadcafd3a9da127b1507275bfac62b9fa55e27490b176dc", + "hash": "fe3b02f68025b90d0ce782885c8f72582642a985694eb4bcd702c2e006846a86", + "title": "lib/binary.tri" + }, + { + "name": "tricu-lib-bytes", + "version": "0.1.0", + "manifest": "16cff955cb9ab44063ed21651002d209ef7d3592fa005cd3dc32e287d6ca5b68", + "hash": "c0a9ffd923b4dd17f6c1fd105502d9e82a9064f75b6312b37c155c94a3ce73d3", + "title": "lib/bytes.tri" + }, + { + "name": "tricu-lib-conversions", + "version": "0.1.0", + "manifest": "78ce6db3557cd57f2c5799989d16a8f40104de5c4485646734a23093dc458a4e", + "hash": "fc37dd8c558961c88211c3f4faf31bc438bcda12384f94125f563f1651e09ac9", + "title": "lib/conversions.tri" + }, + { + "name": "tricu-lib-graph", + "version": "0.1.0", + "manifest": "7b798a3afae6dce07b718bed855c7209ec3b898bb70b379dece935c4033cf9b6", + "hash": "b588b07ac71f87ab85059ea0788ee2e11d3ee77ad319310e5a21f844c98dabf4", + "title": "lib/graph.tri" + }, + { + "name": "tricu-lib-http", + "version": "0.1.0", + "manifest": "e6195e968697ca5799891bcd9096b568dceb717ea6e2b14adbdb8ca041a01691", + "hash": "7f7b4191c8780da6a4bf20084835e67007e9e5a7b9af43476b97faf502338545", + "title": "lib/http.tri" + }, + { + "name": "tricu-lib-intensional", + "version": "0.1.0", + "manifest": "7467e74f0c5b7dfad8d6a14d34171b2b0bcd7750423894e2ca920e0535fde7d1", + "hash": "dd39639f1d0a1a14f7856b8d0db682adf36d1e7501ea1889bd185ea500989380", + "title": "lib/intensionalContracts.tri" + }, + { + "name": "tricu-lib-io", + "version": "0.1.0", + "manifest": "2d23be85d277457fd36c84f5eaa227e94e1c4efec281ff73017aaee109096f49", + "hash": "a51d9fcffd12aebc39166e2ba4e5b86896832db299f06322b7a2805bc4d57f05", + "title": "lib/io.tri" + }, + { + "name": "tricu-lib-lexer", + "version": "0.1.0", + "manifest": "816df1a32853750a1254112aff8ae8c55ca86bf70e809d226969ab1d43a6688b", + "hash": "9bc1c7c66b150fdac8f046b2bad48b07bf585c9ea2c63b416dc72c4191b0128e", + "title": "lib/lexer.tri" + }, + { + "name": "tricu-lib-native-math", + "version": "0.1.0", + "manifest": "7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db", + "hash": "74251492b68205d47f001fe1210d8846b905dae7b4cdf12c3b1c5e563473575d", + "title": "lib/math/native.tri" + }, + { + "name": "tricu-lib-parser", + "version": "0.1.0", + "manifest": "14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d", + "hash": "3d364a349e4a623bc022a6cdc558a490d764c4c9d6a224b65a727f2380ce5b0d", + "title": "lib/parser.tri" + }, + { + "name": "tricu-lib-patterns", + "version": "0.1.0", + "manifest": "703db8cd6c5679861257d1cc38c17be200241ade8db3812e8c387e9274aaa56e", + "hash": "fb81fe47421564ac80fedc90be6003906e017978385f749d2da95297e58587c2", + "title": "lib/patterns.tri" + }, + { + "name": "tricu-lib-prelude", + "version": "0.1.0", + "manifest": "6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823", + "hash": "3e32ef46cd9a7032469c6b004917c9b8982da95673d486a576fc31541bbe51c6", + "title": "lib/prelude.tri" + }, + { + "name": "tricu-lib-socket", + "version": "0.1.0", + "manifest": "49fc19156894c8f5b5a7124760eb8db2ac504404dcda77ae0e3a0dea39983d44", + "hash": "decfff4079c7c202f664a55496926cce1fcd1e9c67cf67b84718bf7d663e6f4d", + "title": "lib/socket.tri" + }, + { + "name": "tricu-lib-source-ast", + "version": "0.1.0", + "manifest": "c6579f89e47a16694f1c08fe9825b183d8bc272e23cd744eb954c106b689c32f", + "hash": "af66062931c5de826bd336625d53c1c354fe6cc736e56e247ae550c542f0fa8a", + "title": "lib/source/ast.tri" + }, + { + "name": "tricu-lib-source-build-stable", + "version": "0.1.0", + "manifest": "b7d49cb984e23aa3a70afdc4044e6f5ba98f3c71b7e78bd9269426c1c061a750", + "hash": "faea17b7579cd7193af19cb74a34266cdf8ac2d9934a24d8552dd09edd5cb4c5", + "title": "lib/source/build-stable.tri" + }, + { + "name": "tricu-lib-source-build", + "version": "0.1.0", + "manifest": "1af31fab093b742c452db406380ea2eb90d399237eab16138e06e4e9196cdaf3", + "hash": "7b7b8b132f1192bf4a9e379b641382167f9be38a609bdad18b144dfa85da2b3c", + "title": "lib/source/build.tri" + }, + { + "name": "tricu-lib-source-bundle", + "version": "0.1.0", + "manifest": "d1af60d301f08b0c8715da80b9c632b04e71270817e0925aec81121734f3d1e6", + "hash": "f13735828b62a6d90e95b2964e5fdf72d4e5181aa49d48c04cf134b5606bc10e", + "title": "lib/source/bundle.tri" + }, + { + "name": "tricu-lib-source-compile", + "version": "0.1.0", + "manifest": "9bd7f27b58f640544318153c8bda76079524d06b2657600043625f613c0620d0", + "hash": "a8d7805b268f93ef72e10c7031bc709fb9924ca91b2eacdd313f70d96d254560", + "title": "lib/source/compile.tri" + }, + { + "name": "tricu-lib-source-core", + "version": "0.1.0", + "manifest": "83e1dc8052f806b19ebc737998bbdfff23211b23a6bbe2ae6adbede8ad1652a2", + "hash": "d7105ef477224dfb10ad2773e54744cb3f87ddf304eb753d7cb9ba40ea9cc3df", + "title": "lib/source/core.tri" + }, + { + "name": "tricu-lib-source-equations", + "version": "0.1.0", + "manifest": "568c5d782a847e4f8d6b7061d51d34fc527a466b872ede27032104293df3bf8f", + "hash": "0a3956e0f6e794d843f56d734b14259c63a6e9ece22ec73d73f8f995f1578fa8", + "title": "lib/source/equations.tri" + }, + { + "name": "tricu-lib-source-export-cache", + "version": "0.1.0", + "manifest": "ba1c6fbb9c4af886b1466e0ea16bc0ceba1c0a60c5ad298c19be0b755e25b11b", + "hash": "8675a2bc53b5820d45cce64c072c55f7e03d23b1b4960a45f952fc6387023024", + "title": "lib/source/export-cache.tri" + }, + { + "name": "tricu-lib-source-index", + "version": "0.1.0", + "manifest": "c2946fe3ac0daf1a06d6f7deab9f7ad08d679c241b04ad9c0c6d3b6038cf091d", + "hash": "1f18232479e776982515edc3fe2c0f39fad79e2b428c2ff040d92edf5441ac6a", + "title": "lib/source/index.tri" + }, + { + "name": "tricu-lib-source-lexer", + "version": "0.1.0", + "manifest": "4cc4ed214d6e474b339c970d04cc09ced20c6472758b58897aabbd6f3a5bbb42", + "hash": "b61e8d7d31f730c1e4db08c729435302e76eb911ee2c45b110f2932a60b2eb33", + "title": "lib/source/lexer.tri" + }, + { + "name": "tricu-lib-source-lock", + "version": "0.1.0", + "manifest": "de672f2d1d040095997894b57a1091f3746d61bcd2e278f263cdbc51ba4391f6", + "hash": "51d352cb5306a96b0275e6cf80c5a7d160e7379cf8f31aa128d96fe3e56043ff", + "title": "lib/source/lock.tri" + }, + { + "name": "tricu-lib-source-map", + "version": "0.1.0", + "manifest": "d1ed18723a9acfd6f0b13ef77ef17883dcbad0d8fb79b772f3263e00551c60dd", + "hash": "e8f5fbfbb768926c5dcc43511fed05a2436f0bf46f2a18c75408496886cb1539", + "title": "lib/source/map.tri" + }, + { + "name": "tricu-lib-source-module", + "version": "0.1.0", + "manifest": "23bbacaee8dba34c8df664877235a65594569adcc91bd2ebc886b32f287e1cd9", + "hash": "20c71797fca0c2d7c6e1a5482da8cfce80292463cba731187645e96dc17dbe2e", + "title": "lib/source/module.tri" + }, + { + "name": "tricu-lib-source-object", + "version": "0.1.0", + "manifest": "dc29e3d043b9dc8685ed05ede1c226b3f14f47c63365b623214cf709a275b3bf", + "hash": "acb79eb9c2f56a18c1c740aaaee97e9e5e53f55b56602bd16a351d85cfadc192", + "title": "lib/source/object.tri" + }, + { + "name": "tricu-lib-source-order", + "version": "0.1.0", + "manifest": "84c021d4a13df85c9d6cdbdb78769f069fa83fba76657c40ccb5a4bed1e91de2", + "hash": "3b4474558c2336c95a122ef32c4f3070ce67b2e0491539f757594a0ac02b0c6a", + "title": "lib/source/order.tri" + }, + { + "name": "tricu-lib-source-parser", + "version": "0.1.0", + "manifest": "59befca0769d80a6d663ffd5224a076c0de88914192a960398a81a4e37e6ae89", + "hash": "5188bb1a7ede262cb63f02daadff9b827c05bd26ace2e7f23528e9dd10ba6121", + "title": "lib/source/parser.tri" + }, + { + "name": "tricu-lib-source-pattern", + "version": "0.1.0", + "manifest": "d14232cb623da7a59883ae5e0c773fa71037a887a7dcf3352e48cc8dff421123", + "hash": "d2842a47b4f76d3d0bf86914620a33b5251319167c74873e7f630923f4b95e68", + "title": "lib/source/pattern.tri" + }, + { + "name": "tricu-lib-source-program", + "version": "0.1.0", + "manifest": "384012eefdf503a49ed1c660a6e07b5e95df73585121f83a8eeae98089f1a1ad", + "hash": "af2b3483281c7c4e24151956dce5d763dfe4deeb4b0ec7635a341b443b2b4584", + "title": "lib/source/program.tri" + }, + { + "name": "tricu-lib-source-resolve", + "version": "0.1.0", + "manifest": "9c0daa3e05f1f7dfad613037e5dea3828aa14ddd509624c69c339d8ff089977a", + "hash": "b82891447d90b9c9bfeef4c8a75d15589ef008d9142e32f8694bd0ce083fb8ca", + "title": "lib/source/resolve.tri" + }, + { + "name": "tricu-lib-source-stable", + "version": "0.1.0", + "manifest": "5189315a72af93ee9fe3dbc8c73e07e97b980b4c91b9c2f6244d447461db55dd", + "hash": "10dfca05efdf0113e65f5cb77de96b5e8d768c9e9749b05cda1e344715a44230", + "title": "lib/source/stable.tri" + }, + { + "name": "tricu-lib-source-staged-conditional-experiment", + "version": "0.1.0", + "manifest": "f09eb17db370560404991726c7961b9d05992077beb54051bb0dac2e9f54c57c", + "hash": "aabb749e392a47605ffd08f12ec442747641d190ca2c4240f3196744f6fdbd22", + "title": "lib/source/staged-conditional-experiment.tri" + }, + { + "name": "tricu-lib-source-staged-list-experiment", + "version": "0.1.0", + "manifest": "c1c062475b966bd6adae0148db1751959400f59ba73c6f84ca0e561599639e98", + "hash": "eac98c45250ba80f2331cb71128306b25bd61b4e8e3e063b9b635ec654f4d698", + "title": "lib/source/staged-list-experiment.tri" + }, + { + "name": "tricu-lib-source-staging-experiment", + "version": "0.1.0", + "manifest": "db8e78afce2dadd987a2e7840b1107da75d3cc9c4ac3e5cd217cf0bc2ff00790", + "hash": "bd742a4ec55cf68f1f1b382979fdf6b5c098039089be16c76b4621b8ca07d9cb", + "title": "lib/source/staging-experiment.tri" + }, + { + "name": "tricu-lib-source-unit", + "version": "0.1.0", + "manifest": "908400c8137869ba4313fa875fc2bf87db8a736debddd5bf2a40d6147295158f", + "hash": "30715cbaf97e966bcb8ef49c9f5da1fca571308db49b103b428de713b9ad302f", + "title": "lib/source/unit.tri" + }, + { + "name": "tricu-lib-arboricx-inspect", + "version": "0.1.0", + "manifest": "fe9b420e1e776fa1dda7b77857e322c0509ed308bb18441b76a3b03023f93468", + "hash": "f571888c5aa3f7a91e9d5d6c45c674851ea8e3598514ad8d535fd3e9056d0314", + "title": "lib/arboricx/inspect.tri" + }, + { + "name": "tricu-lib-packages-base", + "version": "0.1.0", + "manifest": "fa9d4df0f82cac2754fdd3e92009cb48064856ff4cc5b18f092309aef7ff5ed4", + "hash": "f9f0ab0e44f6ae39479d74c6c66a2bdaba3f40bd26781c3ec95300c2ee3c07f3", + "title": "lib/packages/base.tri" + }, + { + "name": "tricu-lib-packages-io", + "version": "0.1.0", + "manifest": "6a22866c2cff143599cb854b2cd3bb3c8948e40835425ed62d942d88bed5c5aa", + "hash": "401961d889131c735bf48b415f53d3b85dfab0136496299f60cf1dcb0b264f14", + "title": "lib/packages/io.tri" + }, + { + "name": "tricu-lib-recursion-list", + "version": "0.1.0", + "manifest": "4c79b7ad124027147b8fddd98c2b66cfd776c36d915c95dfb1fbf9b31a51fb88", + "hash": "60afc41f04fa65130326eeed4ca9e128bee5e90c7041f9641bbf9cfe87c142cd", + "title": "lib/recursion/list.tri" + }, + { + "name": "tricu-lib-source-bundle-stable", + "version": "0.1.0", + "manifest": "a06948780686a4432f97ce0a7ab5f8ed66a535a6d5563275e5f32375a679cb59", + "hash": "3de401378f33dd8f93e9ca11c1c2bd73a458dabcd8d631a33ba17306f83d7d3b", + "title": "lib/source/bundle-stable.tri" + }, + { + "name": "tricu-lib-tools-format-tri", + "version": "0.1.0", + "manifest": "e8bad7dcea5944336083f5bfa3ada63d7542286fbdec0f34dfeb65e9879ba2fc", + "hash": "3bd4df273ab4e4599417a18210ec3ad39e2ace2f7df6c0b7cad62999c4cb52a2", + "title": "lib/tools/format-tri.tri" + }, + { + "name": "parser-demo", + "version": "0.1.6", + "hash": "355e41506f39e05da8c8a72a68aa810a486e062480322bac11af67e86980520e", + "manifest": "0c34bfdf800f8bd1b742e375a8f7c555c88d0c827268f684259433e834d94fed", + "title": "Parser combinators: complete input, prefixes and committed errors", + "demo": "parser" + }, + { + "name": "lexer-demo", + "version": "0.1.6", + "hash": "e756a481b3056a2e76f50316ccf77bfab8b15727b7bec899580c2eb919e668b2", + "manifest": "ed99e054e9c862668e165f458d3afcdc56279f766eea7a3886d440aea7252b63", + "title": "Located scans: matched prefix, remainder and character positions", + "demo": "lexer" + }, + { + "name": "intro", + "version": "0.2.0", + "hash": "64e7db3b35121efa19c7becbbb38a0ad0f884143e790e286a5ee6c236c00f9d5", + "manifest": "1e1778f9b556444195c59bc98002837311bf926c2a6822456a4651f74c6e5113", + "title": "Start here", + "demo": "intro" + }, + { + "name": "greet", + "version": "0.2.0", + "hash": "0811457d501113ee11194f90e279ebb4ef9d548c70cb48d146be03eb9af7505f", + "manifest": "c2abf7b96cbc820eeb5ae5d5afcf8ec270f06b3a4eebfc00b6ff6c526f3b099b", + "title": "A conversation", + "demo": "greet" + }, + { + "name": "microscope", + "version": "0.2.0", + "hash": "493a125b649639c0df8348b4aeb3a455b7139cae0634ba114866c48813500bc5", + "manifest": "095aa94589307f9c8fb2b7e6c8dd4e63cc31ab2cac33e780882867df4cfe1a23", + "title": "Tree microscope", + "demo": "microscope" + }, + { + "name": "rgb", + "version": "0.2.0", + "hash": "b8c0e21c09f63511794cc62827a6b231e62a55f7e779022a1b740aaba29b0368", + "manifest": "e37bd20d45ecd6b3721aa1af12deb7284fe6c9c079741c36e11ab07726316309", + "title": "RGB validator", + "demo": "rgb" + }, + { + "name": "shipping", + "version": "0.2.0", + "hash": "4aa9ce9f19dfce87ecb3f6bd0a2e881dafcbcd3d2e4b4075befbb378d80833ea", + "manifest": "dcdd3568bca3bef06919c3de6449d78a400b6156a27cf90dd2a5bdbc8ec64d8f", + "title": "Shipping policies", + "demo": "shipping" + }, + { + "name": "events", + "version": "0.2.0", + "hash": "8b51693c63658d59c8083ec1c95cf1f6565ce5799791f540e92caf508613c9fb", + "manifest": "a0c4ab3bc22f01eb18f60391d08f64cadb767253eec1ba54016d2f6441286c44", + "title": "Event adapters", + "demo": "events" + }, + { + "name": "registration", + "version": "0.2.0", + "hash": "679733e17a86cc5e3f5282ca824cad4c9c0febd260e51f6a87e16dd14c02c45a", + "manifest": "e5271ade40a68b9fad92f531859c4411b3ef5773533b36f60a6a1a02dc680a36", + "title": "Registration validator", + "demo": "registration" + }, + { + "name": "migration", + "version": "0.2.0", + "hash": "730aeb8203ff504b7483999a6477a292b10871f82e94a77d3d5f7b49ecc3b6b3", + "manifest": "0713754ddf34e447f3581fc105226da560f0c6533f1e08b666057e061866b600", + "title": "Profile migrations", + "demo": "migration" } ] } diff --git a/ext/demo-site/parser-demo.json b/ext/demo-site/parser-demo.json @@ -1,9 +1,10 @@ { "id": "parser", + "source": "!import 6aa33a710955e5746f322775b9078f57ba4145f6b723ff4b76a292285e919823 *\n!import 14282088469cc420dd014700da06998f6bb8dcf990fc885a464c0a1e1858e20d *\n!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N\n!export parseNames\n!export parsePrefix\n\n-- Lowercase names separated by commas. Try \"red,green\", \"red,,blue\",\n-- \"red,\" and \"red green\". A comma commits to another name.\n-- parseNames requires the entire input; parsePrefix exposes any remainder.\n-- Edit the parser or labels below; valid edits compile locally.\n-- Imports pin complete library interfaces, fetched only when compiling.\nnameParser = parserLabel \"lowercase name\" (parserSome (parserSatisfy (c : N.inRange c 97 122)))\ncommaParser = parserThen (parserExpect 44) parserCommit\nnamesPrefix = parserSepBy1 nameParser commaParser\nnamesComplete = parserBefore namesPrefix (parserLabel \"end of input\" parserEof)\n\nreport reply = (parserMatchReply\n (diagnostic rest consumed committed : [\n [\"status\" 0 \"error\"]\n [\"expected\" 0 (parserDiagnosticExpected diagnostic)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n (names rest consumed committed : [\n [\"status\" 0 \"ok\"]\n [\"names\" 0 (intercalate \", \" names)]\n [\"count\" 1 (length names)]\n [\"remaining\" 0 rest]\n [\"consumed\" 2 consumed]\n [\"committed\" 2 committed]])\n reply)\nparseNames text = report (namesComplete text)\nparsePrefix text = report (namesPrefix text)\n", "hash": "355e41506f39e05da8c8a72a68aa810a486e062480322bac11af67e86980520e", "mode": "pure", "compilerSha256": "d70de875988dfa309f2c167992928866f88b08af351918b8c7b5d88c541c6e94", - "sourceSha256": "3405e18774db8de759b7793880e1568c156d68e5fe4a388e09b95ff301d896f5", + "sourceSha256": "18aa0a464dabb595749abdab5edb1bb11c4356c0e753cf0985a644901bb5c241", "haskellCases": [ { "export": "parseNames", diff --git a/ext/demo-site/prepare-index.py b/ext/demo-site/prepare-index.py @@ -82,7 +82,7 @@ def main(): raise ValueError('Native demos are released through prepare-showcase.py, not prepare-index.py') if not any(r.get('demo') == entry['id'] and r['hash'] == entry['hash'] for r in previous): raise ValueError('Native demo has no accepted release: ' + entry['id']) - continue # Preserve its exact pin and read-only native-module source. + continue # Preserve its accepted native source and explicit editability metadata. # Operator-owned release labels. Refuse changed contents at a label; # add/change a version explicitly rather than silently repointing it. matches = [r for r in previous if r.get('demo') == entry['id'] and r['hash'] == entry['hash']] @@ -100,7 +100,7 @@ def main(): releases[releases.index(existing)] = release else: releases.append(release) - entry['environment'] = 'practical' if entry['id'] in ['shipping', 'events', 'registration', 'migration'] else 'empty' + entry['environment'] = 'empty' # Current demos declare imports, never implicit profiles. (HERE / 'bundles' / (support_hash + '.arboricx')).write_bytes(data) (HERE / 'environments.json').write_text(json.dumps(profiles, indent=2) + '\n') (HERE / 'packages.json').write_text(json.dumps(dict(schema=1, releases=releases), indent=2) + '\n') diff --git a/ext/demo-site/prepare-libraries.py b/ext/demo-site/prepare-libraries.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Publish the complete declared interface of every lib/**/*.tri module. + +Retained modules are projected from authenticated compiler/support fixtures. +Other library sources are compiled against those exact modules with the packaged +stable compiler. The native host supplies every manifest identity. Preparation +stages immutable release assets locally. Run with a Nix-built host. +""" +import argparse +import hashlib +import json +from pathlib import Path +import re +import subprocess +import sys +import tempfile + +HERE = Path(__file__).resolve().parent +ROOT = HERE.parent.parent +sys.path.insert(0, str(ROOT / 'test')) +from bundle_dag import read, merge_bundles +from fixture_sources import source_rows, verify, current_mismatches +from shipped_compiler import verify as verify_compiler + + +def library_sources(): + """Coverage is filesystem-derived; newly added libraries cannot be omitted.""" + fixtures = ROOT / 'test/fixtures' + retained = {row[3]: row for row in source_rows(fixtures)} + result = [] + for path in sorted((ROOT / 'lib').rglob('*.tri')): + relative = str(path.relative_to(ROOT)) + row = retained.get(relative) + alias = row[2] if row else re.sub(r'[^A-Za-z0-9_]', '_', str(path.relative_to(ROOT / 'lib').with_suffix(''))) + result.append((alias, relative, row[0] if row else None)) + if len({r[0] for r in result}) != len(result): + raise ValueError('Library module alias collision') + return result + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('tricu', type=Path) + parser.add_argument('--version', required=True, help='New immutable release version') + parser.add_argument('--stage-site', action='store_true') + args = parser.parse_args() + if not re.fullmatch(r'[A-Za-z0-9][A-Za-z0-9._-]{0,127}', args.version): + raise ValueError('Invalid version') + verify(ROOT / 'test/fixtures') + compiler_metadata = verify_compiler() + if current_mismatches(ROOT / 'test/fixtures', ROOT): + raise ValueError('Working sources differ from authenticated fixtures') + compiler = json.loads((HERE / 'compiler.json').read_text()) + if hashlib.sha256((ROOT / 'test/fixtures/compiler-library.arboricx').read_bytes()).hexdigest() != compiler['hash']: + raise ValueError('Site/compiler fixture mismatch') + host = args.tricu.resolve() + index = json.loads((HERE / 'packages.json').read_text()) + releases = list(index['releases']) + with tempfile.TemporaryDirectory(prefix='tricu-all-libraries-') as temporary: + work = Path(temporary) + workspace = work / 'workspace' + workspace.mkdir() + (workspace / 'tricu.workspace').write_text('tricu.workspace.v1\n') + artifacts = {} + def run(*words): + reply = subprocess.run([str(host), *map(str, words), '+RTS', '-N1', '-M2048m', '-RTS'], + cwd=workspace, capture_output=True, timeout=300) + if reply.returncode: + raise RuntimeError((reply.stdout + reply.stderr).decode()) + return reply.stdout.decode() + def publish(alias, relative, bundle): + data = bundle.read_bytes() + _, _, nodes, exports, _ = read(bundle) + if not exports or len(exports) > 4096 or len(nodes) > 100000 or len(data) > 16777216: + raise ValueError('Library exceeds browser transport bounds: ' + relative) + name = 'tricu-lib-' + alias.replace('_', '-') + output = run('package', 'publish', '--root', work / 'registry', '--name', name, + '--version', args.version, '--file', bundle) + _, row = output.strip().splitlines() + actual_name, version, manifest, digest = row.split('\t') + assert (actual_name, version, digest) == (name, args.version, hashlib.sha256(data).hexdigest()) + # Independently import the exact transport bytes used by browser fetch. + imported = run('arboricx', 'import', '--indexed', '--store', work / 'store', '--file', bundle) + assert re.search(r'Created module alias .* -> ([0-9a-f]{64})', imported)[1] == manifest + release = dict(name=name, version=version, manifest=manifest, hash=digest, title=relative) + old = next((r for r in releases if (r['name'], r['version']) == (name, version)), None) + if old and (old['hash'], old['manifest']) != (digest, manifest): + raise ValueError('Immutable release changed: ' + name) + if not old: + releases.append(release) + artifacts[digest] = data + (workspace / (alias + '.tri')).write_text('!export * from ' + manifest + '\n') + print(f'{relative}: {len(exports)} exports, {len(data)} bytes, {manifest}', flush=True) + + imported_compiler = run('arboricx', 'import', '--indexed', '--store', work / 'tools', + '--file', ROOT / compiler_metadata['bundle']) + compiler_manifest = re.search(r'Created module alias .* -> ([0-9a-f]{64})', imported_compiler)[1] + sources = library_sources() + package_names = ['tricu-lib-' + alias.replace('_', '-') for alias, _, _ in sources] + if len(set(package_names)) != len(package_names): + raise ValueError('Library package name collision') + for alias, relative, cohort in sources: + if cohort is None: + continue + original = ROOT / 'test/fixtures' / (cohort + '.arboricx') + names = [(name, name[len(alias) + 1:]) for name in read(original)[3] if name.startswith(alias + '.')] + if not names: + raise ValueError('Missing retained public interface: ' + relative) + bundle = work / (alias + '.arboricx') + merge_bundles(bundle, [(original, names)], prune_unreachable=True) + publish(alias, relative, bundle) + + # Source modules declare these explicit build inputs for library consumers. + (workspace / 'recursion_support.tri').write_text('!import prelude as B\n!export pair\npair = B.pair\n') + (workspace / 'recursion.tri').write_text('!export * from recursion_list\n') + (workspace / 'format_support.tri').write_text(''.join('!export * from ' + name + '\n' for name in + ['prelude', 'parser', 'source_lexer', 'source_equations', 'source_ast'])) + (workspace / 'bundle_support.tri').write_text('!export * from prelude\n!export * from source_bundle\n') + for alias, relative, cohort in sources: + if cohort is None: + (workspace / (alias + '.tri')).write_bytes((ROOT / relative).read_bytes()) + for alias, relative, cohort in sources: + if cohort is not None: + continue + bundle = work / (alias + '.arboricx') + run('arboricx', 'compile', '--file', workspace / (alias + '.tri'), '--store', work / 'store', + '--toolchain', compiler_manifest, '--tool-store', work / 'tools', + '--output', bundle, '--compile-timeout', '270') + publish(alias, relative, bundle) + if args.stage_site: + # Validate the whole batch before modifying the site. Existing object + # and release bytes are immutable; historical releases stay indexed. + for digest, data in artifacts.items(): + target = HERE / 'bundles' / (digest + '.arboricx') + if target.exists() and target.read_bytes() != data: + raise ValueError('Existing bundle integrity failure') + for digest, data in artifacts.items(): + (HERE / 'bundles' / (digest + '.arboricx')).write_bytes(data) + target = HERE / 'packages.json' + pending = target.with_suffix('.json.tmp') + pending.write_text(json.dumps(dict(schema=1, releases=releases), indent=2) + '\n') + pending.replace(target) + print(f'Validated {len(sources)} complete library interfaces' + ('; staged site assets' if args.stage_site else ' (not staged)')) + + +if __name__ == '__main__': + main() diff --git a/ext/demo-site/prepare-showcase.py b/ext/demo-site/prepare-showcase.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 """Opt-in Haskell publication of accepted library roots and native parser/lexer demos. -No fixture regeneration or public-network access. Requires current sources to -match authenticated retained fixtures. Stages only after bounded acceptance. +Compiles locally against authenticated retained fixtures and matching sources. +Stages release assets after bounded acceptance. """ import argparse import hashlib @@ -138,6 +138,7 @@ def main(): parser.add_argument('tricu', type=Path) parser.add_argument('--directory', type=Path, required=True, help='New retained output directory') parser.add_argument('--reuse-directory', action='store_true', help='Reuse a local CAS; sources are rewritten and native receipts checked again') + parser.add_argument('--demos-only', action='store_true', help='Refresh parser/lexer demos against existing library releases without republishing libraries') parser.add_argument('--stage-site', action='store_true', help='After acceptance, stage into this static site') parser.add_argument('--version', default='0.1.1', help='New exact release label for the package set; existing versions remain immutable') args = parser.parse_args() @@ -199,46 +200,16 @@ def main(): if demo: release['demo'] = demo artifacts[pin] = bundle; report['releases'].append(release) return release - published('tricu-compiler', 'Compiler library (stable browser source-unit API; native helpers)', compiler_library) - builder = published('tricu-source-builder', 'Stable native application compiler (modules, imports and publication)', ROOT / metadata['bundle']) - report['sourceBuilderSha256'] = metadata['sha256'] - report['browserCompilerSha256'] = descriptor['hash'] - for name, alias, cohort, title in LIBRARIES: - published(name, title, extracted(alias, cohort)) - def tree_list(values): return ''.join('2' + tree for tree in values) + '0' - def result_tree(success, value, rest): return '2' + ('10' if success else '0') + '2' + value + rest - checks = [ - ('tricu-math', 'add', [of_number(123456789), of_number(11)], of_number(123456800)), - ('tricu-math', 'divMod', [of_number(100), of_number(7)], '2' + of_number(14) + of_number(2)), - ('tricu-math', 'divMod', [of_number(100), of_number(0)], '2' + of_number(0) + of_number(100)), - ('tricu-binary', 'readU8', [tree_list([of_number(65), of_number(66)])], - result_tree(True, of_number(65), tree_list([of_number(66)]))), - ('tricu-binary', 'readU8', [tree_list([of_number(256)])], - result_tree(False, of_number(15), tree_list([of_number(256)]))), - ('tricu-binary', 'binaryUtf8?', [tree_list([of_number(195), of_number(169)])], '10'), - ('tricu-binary', 'binaryUtf8?', [tree_list([of_number(192), of_number(175)])], '0'), - ] - report['libraryCases'] = [] - for name, export, trees, expected in checks: - manifest = next(r['manifest'] for r in report['releases'] if r['name'] == name) - arguments = [] - for i, tree in enumerate(trees): - path = root / ('library-arg-' + str(i) + '.tree'); path.write_bytes(bytes(map(int, tree))) - arguments.extend(['--arg-tree-file', path]) - actual = run('arboricx', 'run', '--store', root / 'consumer', '--module', manifest, - '--name', export, *arguments, '--format', 'ternary') - assert actual == expected, (name, export, actual[:200], expected) - report['libraryCases'].append(dict(name=name, export=export, arguments=trees, result=actual)) - for alias in ['prelude', 'parser', 'lexer', 'source_lexer', 'source_equations', 'source_ast', 'native_math']: - pin = imported(extracted(alias, 'compiler')) - (workspace / (alias + '.tri')).write_text('!export * from ' + pin + '\n') - for alias, source in [('recursion', ROOT / 'lib/recursion/list.tri'), ('formatter', ROOT / 'lib/tools/format-tri.tri'), - ('parser_demo', HERE / 'demos/parser.tri'), ('lexer_demo', HERE / 'demos/lexer.tri')]: - data = source.read_bytes(); (workspace / (alias + '.tri')).write_bytes(data) - report['sourceSha256'][str(source.relative_to(ROOT))] = hashlib.sha256(data).hexdigest() - (workspace / 'recursion_support.tri').write_text('!import prelude as B\n!export pair\npair = B.pair\n') - (workspace / 'format_support.tri').write_text(''.join('!export * from ' + name + '\n' for name in - ['prelude', 'parser', 'source_lexer', 'source_equations', 'source_ast'])) + # The editable demos use the site's exact published manifest references. + releases = json.loads((HERE / 'packages.json').read_text())['releases'] + refs = set() + for name in ['parser', 'lexer']: + refs.update(re.findall(r'^!import ([0-9a-f]{64}) ', (HERE / 'demos' / (name + '.tri')).read_text(), re.M)) + for ref in sorted(refs): + release = next(r for r in releases if r['manifest'] == ref) + bundle = HERE / 'bundles' / (release['hash'] + '.arboricx') + assert hashlib.sha256(bundle.read_bytes()).hexdigest() == release['hash'] + assert imported(bundle) == ref compiler = imported(ROOT / metadata['bundle'], root / 'tools') def compile_unit(alias): bundle = root / (alias + '.arboricx') @@ -246,46 +217,92 @@ def main(): '--toolchain', compiler, '--tool-store', root / 'tools', '--output', bundle, '--compile-timeout', '180', seconds=195) return bundle, imported(bundle) - # Exercise the actual published builder through its native CLI ABI, with a - # local dependency and a fresh store. No sockets, public registry or fallback. - (workspace / 'probe_dep.tri').write_text('!export answer\nanswer = 42\n') - (workspace / 'builder_probe.tri').write_text('!import probe_dep as D\n!export main\nmain = D.answer\n') - probe = root / 'builder-probe.arboricx' - run('arboricx', 'compile', '--file', workspace / 'builder_probe.tri', '--store', root / 'builder-probe-store', - '--toolchain', builder['manifest'], '--tool-store', root / 'consumer', '--output', probe, - '--compile-timeout', '45', seconds=60) - probe_manifest = imported(probe, root / 'builder-probe-consumer') - assert run('arboricx', 'run', '--store', root / 'builder-probe-consumer', '--module', probe_manifest, - '--name', 'main', '--format', 'number') == '42' - (workspace / 'missing_dep.tri').write_text('!import absent_showcase_dependency as M\n!export main\nmain = M.answer\n') - run('arboricx', 'compile', '--file', workspace / 'missing_dep.tri', '--store', root / 'builder-probe-store', - '--toolchain', builder['manifest'], '--tool-store', root / 'consumer', '--output', root / 'must-not-exist.arboricx', - '--compile-timeout', '45', seconds=60, success=False) - assert not (root / 'must-not-exist.arboricx').exists(), 'failed build emitted executable' - recursion_bundle, _ = compile_unit('recursion') - published('tricu-list-traversal', 'Early-stopping list folds with retained input suffixes', recursion_bundle) - patterns = next(r for r in report['releases'] if r['name'] == 'tricu-patterns') - traversal = next(r for r in report['releases'] if r['name'] == 'tricu-list-traversal') - assert imported(artifacts[patterns['hash']]) == patterns['manifest'] - assert imported(artifacts[traversal['hash']]) == traversal['manifest'] - (workspace / 'published_patterns.tri').write_text('!export * from ' + patterns['manifest'] + '\n') - (workspace / 'published_traversal.tri').write_text('!export * from ' + traversal['manifest'] + '\n') - probe_source = (HERE / 'test/showcase-library-probe.tri').read_bytes() - report['sourceSha256']['ext/demo-site/test/showcase-library-probe.tri'] = hashlib.sha256(probe_source).hexdigest() - (workspace / 'library_probe.tri').write_bytes(probe_source) - library_probe, library_manifest = compile_unit('library_probe') - expected = tree_list([of_number(13), of_number(99), '0', '2' + of_number(3) + tree_list([of_number(0), of_number(9)])]) - actual = run('arboricx', 'run', '--store', store, '--module', library_manifest, '--name', 'main', '--format', 'ternary') - assert actual == expected, 'published dispatch/list traversal probe' - report['libraryProbe'] = dict(result=actual, bundleSha256=hashlib.sha256(library_probe.read_bytes()).hexdigest()) - formatter, formatter_manifest = compile_unit('formatter') - # Independent real formatter cases, no file effects or diverging probe needed. - for label, before, expected in json.loads((ROOT / 'test/formatter_cases.json').read_text()): - input_file = root / 'formatter-input.tri'; input_file.write_text(before) - actual = run('format', input_file, '--formatter', formatter_manifest, '--tool-store', store, strip=False) - assert input_file.read_bytes() == before.encode(), label - assert actual == expected, (label, repr(actual), repr(expected)) - published('tricu-formatter', 'Conservative tricu equation alignment (not an AST printer)', formatter) + for name in ['parser', 'lexer']: + source = HERE / 'demos' / (name + '.tri') + data = source.read_bytes() + (workspace / (name + '_demo.tri')).write_bytes(data) + report['sourceSha256'][str(source.relative_to(ROOT))] = hashlib.sha256(data).hexdigest() + if not args.demos_only: + published('tricu-compiler', 'Compiler library (stable browser source-unit API; native helpers)', compiler_library) + builder = published('tricu-source-builder', 'Stable native application compiler (modules, imports and publication)', ROOT / metadata['bundle']) + report['sourceBuilderSha256'] = metadata['sha256'] + report['browserCompilerSha256'] = descriptor['hash'] + for name, alias, cohort, title in LIBRARIES: + published(name, title, extracted(alias, cohort)) + def tree_list(values): return ''.join('2' + tree for tree in values) + '0' + def result_tree(success, value, rest): return '2' + ('10' if success else '0') + '2' + value + rest + checks = [ + ('tricu-math', 'add', [of_number(123456789), of_number(11)], of_number(123456800)), + ('tricu-math', 'divMod', [of_number(100), of_number(7)], '2' + of_number(14) + of_number(2)), + ('tricu-math', 'divMod', [of_number(100), of_number(0)], '2' + of_number(0) + of_number(100)), + ('tricu-binary', 'readU8', [tree_list([of_number(65), of_number(66)])], + result_tree(True, of_number(65), tree_list([of_number(66)]))), + ('tricu-binary', 'readU8', [tree_list([of_number(256)])], + result_tree(False, of_number(15), tree_list([of_number(256)]))), + ('tricu-binary', 'binaryUtf8?', [tree_list([of_number(195), of_number(169)])], '10'), + ('tricu-binary', 'binaryUtf8?', [tree_list([of_number(192), of_number(175)])], '0'), + ] + report['libraryCases'] = [] + for name, export, trees, expected in checks: + manifest = next(r['manifest'] for r in report['releases'] if r['name'] == name) + arguments = [] + for i, tree in enumerate(trees): + path = root / ('library-arg-' + str(i) + '.tree'); path.write_bytes(bytes(map(int, tree))) + arguments.extend(['--arg-tree-file', path]) + actual = run('arboricx', 'run', '--store', root / 'consumer', '--module', manifest, + '--name', export, *arguments, '--format', 'ternary') + assert actual == expected, (name, export, actual[:200], expected) + report['libraryCases'].append(dict(name=name, export=export, arguments=trees, result=actual)) + for alias in ['prelude', 'parser', 'lexer', 'source_lexer', 'source_equations', 'source_ast', 'native_math']: + pin = imported(extracted(alias, 'compiler')) + (workspace / (alias + '.tri')).write_text('!export * from ' + pin + '\n') + for alias, source in [('recursion', ROOT / 'lib/recursion/list.tri'), ('formatter', ROOT / 'lib/tools/format-tri.tri'), + ('parser_demo', HERE / 'demos/parser.tri'), ('lexer_demo', HERE / 'demos/lexer.tri')]: + data = source.read_bytes(); (workspace / (alias + '.tri')).write_bytes(data) + report['sourceSha256'][str(source.relative_to(ROOT))] = hashlib.sha256(data).hexdigest() + (workspace / 'recursion_support.tri').write_text('!import prelude as B\n!export pair\npair = B.pair\n') + (workspace / 'format_support.tri').write_text(''.join('!export * from ' + name + '\n' for name in + ['prelude', 'parser', 'source_lexer', 'source_equations', 'source_ast'])) + # Exercise the actual published builder through its native CLI ABI, with a + # local dependency and a fresh store. No sockets, public registry or fallback. + (workspace / 'probe_dep.tri').write_text('!export answer\nanswer = 42\n') + (workspace / 'builder_probe.tri').write_text('!import probe_dep as D\n!export main\nmain = D.answer\n') + probe = root / 'builder-probe.arboricx' + run('arboricx', 'compile', '--file', workspace / 'builder_probe.tri', '--store', root / 'builder-probe-store', + '--toolchain', builder['manifest'], '--tool-store', root / 'consumer', '--output', probe, + '--compile-timeout', '45', seconds=60) + probe_manifest = imported(probe, root / 'builder-probe-consumer') + assert run('arboricx', 'run', '--store', root / 'builder-probe-consumer', '--module', probe_manifest, + '--name', 'main', '--format', 'number') == '42' + (workspace / 'missing_dep.tri').write_text('!import absent_showcase_dependency as M\n!export main\nmain = M.answer\n') + run('arboricx', 'compile', '--file', workspace / 'missing_dep.tri', '--store', root / 'builder-probe-store', + '--toolchain', builder['manifest'], '--tool-store', root / 'consumer', '--output', root / 'must-not-exist.arboricx', + '--compile-timeout', '45', seconds=60, success=False) + assert not (root / 'must-not-exist.arboricx').exists(), 'failed build emitted executable' + recursion_bundle, _ = compile_unit('recursion') + published('tricu-list-traversal', 'Early-stopping list folds with retained input suffixes', recursion_bundle) + patterns = next(r for r in report['releases'] if r['name'] == 'tricu-patterns') + traversal = next(r for r in report['releases'] if r['name'] == 'tricu-list-traversal') + assert imported(artifacts[patterns['hash']]) == patterns['manifest'] + assert imported(artifacts[traversal['hash']]) == traversal['manifest'] + (workspace / 'published_patterns.tri').write_text('!export * from ' + patterns['manifest'] + '\n') + (workspace / 'published_traversal.tri').write_text('!export * from ' + traversal['manifest'] + '\n') + probe_source = (HERE / 'test/showcase-library-probe.tri').read_bytes() + report['sourceSha256']['ext/demo-site/test/showcase-library-probe.tri'] = hashlib.sha256(probe_source).hexdigest() + (workspace / 'library_probe.tri').write_bytes(probe_source) + library_probe, library_manifest = compile_unit('library_probe') + expected = tree_list([of_number(13), of_number(99), '0', '2' + of_number(3) + tree_list([of_number(0), of_number(9)])]) + actual = run('arboricx', 'run', '--store', store, '--module', library_manifest, '--name', 'main', '--format', 'ternary') + assert actual == expected, 'published dispatch/list traversal probe' + report['libraryProbe'] = dict(result=actual, bundleSha256=hashlib.sha256(library_probe.read_bytes()).hexdigest()) + formatter, formatter_manifest = compile_unit('formatter') + # Independent real formatter cases, no file effects or diverging probe needed. + for label, before, expected in json.loads((ROOT / 'test/formatter_cases.json').read_text()): + input_file = root / 'formatter-input.tri'; input_file.write_text(before) + actual = run('format', input_file, '--formatter', formatter_manifest, '--tool-store', store, strip=False) + assert input_file.read_bytes() == before.encode(), label + assert actual == expected, (label, repr(actual), repr(expected)) + published('tricu-formatter', 'Conservative tricu equation alignment (not an AST printer)', formatter) parser_bundle, parser_manifest = compile_unit('parser_demo') goldens = [] for export, text, expected in parser_cases(): @@ -296,10 +313,10 @@ def main(): release = published('parser-demo', 'Parser combinators: complete input, prefixes and committed errors', parser_bundle, 'parser') source = (HERE / 'demos/parser.tri').read_bytes() preset = dict(arguments=[dict(type='string', value='red,green,blue')], output='record', mode='pure') - demo = dict(id='parser', preparation='native', title='Parser combinators', hash=release['hash'], source=source.decode(), + demo = dict(id='parser', preparation='native', environment='empty', title='Parser combinators', hash=release['hash'], source=source.decode(), sourceSha256=hashlib.sha256(source).hexdigest(), export='parseNames', **preset, presets={name: preset for name in ['parseNames', 'parsePrefix']}) - goldens = dict(id='parser', hash=release['hash'], mode='pure', compilerSha256=metadata['sha256'], + goldens = dict(id='parser', source=source.decode(), hash=release['hash'], mode='pure', compilerSha256=metadata['sha256'], sourceSha256=hashlib.sha256(source).hexdigest(), haskellCases=goldens) demos, vectors = [demo], [goldens] lexer_bundle, lexer_manifest = compile_unit('lexer_demo') @@ -313,10 +330,10 @@ def main(): source = (HERE / 'demos/lexer.tri').read_bytes() word = dict(arguments=[dict(type='string', value='hello,world')], output='record', mode='pure') whitespace = dict(arguments=[dict(type='string', value=' \n\tword')], output='record', mode='pure') - demos.append(dict(id='lexer', preparation='native', title='Located lexer scans', hash=release['hash'], source=source.decode(), + demos.append(dict(id='lexer', preparation='native', environment='empty', title='Located lexer scans', hash=release['hash'], source=source.decode(), sourceSha256=hashlib.sha256(source).hexdigest(), export='scanWord', **word, presets=dict(scanWord=word, scanWhitespace=whitespace))) - vectors.append(dict(id='lexer', hash=release['hash'], mode='pure', compilerSha256=metadata['sha256'], + vectors.append(dict(id='lexer', source=source.decode(), hash=release['hash'], mode='pure', compilerSha256=metadata['sha256'], sourceSha256=hashlib.sha256(source).hexdigest(), haskellCases=cases)) report['complete'] = True; report['elapsedSeconds'] = time.monotonic()-started; save() if args.stage_site: stage(HERE, artifacts, report['releases'], demos, vectors) diff --git a/ext/demo-site/prepare.py b/ext/demo-site/prepare.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Opt-in stable single-unit demo compilation / Haskell goldens. No library builds. +"""Opt-in native manifest-module demo compilation / Haskell goldens. No library builds. Run after nix build .#: python3 ext/demo-site/prepare.py result/bin/tricu --backend stable """ import argparse @@ -9,9 +9,13 @@ from pathlib import Path import re import subprocess import tempfile +import sys HERE = Path(__file__).resolve().parent ROOT = HERE.parent.parent +sys.path.insert(0, str(ROOT / 'test')) +from shipped_compiler import verify +from bundle_dag import read def digest(data): @@ -104,6 +108,7 @@ def main(): if args.compiler_export.rsplit('.', 1)[-1] != 'compileStableModuleDefinitions': parser.error('compiler export must explicitly select compileStableModuleDefinitions') host, compiler = args.tricu.resolve(), args.compiler_bundle.resolve() + native_metadata = verify() with tempfile.TemporaryDirectory(prefix='tricu-demo-prepare-') as temporary: temp = Path(temporary) store = temp / 'store' @@ -144,8 +149,8 @@ def main(): 'identity': dict(arguments=[dict(type='string', value='Hello!')], output='string', mode='pure'), 'first': dict(arguments=[dict(type='number', value='7'), dict(type='number', value='9')], output='number', mode='pure'), 'greeting': dict(arguments=[], output='string', mode='pure'), - 'numbers': dict(arguments=[], output='list', mode='pure'), - **{name: dict(arguments=[], output='tree', mode='pure') for name in ['leaf', 'stem', 'fork']}, + 'numbers': dict(arguments=[], output='bytes', mode='pure'), + **{name: dict(arguments=[], output='tricu', mode='pure') for name in ['leaf', 'stem', 'fork']}, } settings['microscope']['presets'] = { 'shape': dict(arguments=[dict(type='tree', value='21100')], output='string', mode='pure'), @@ -154,9 +159,6 @@ def main(): } settings.update(practical.settings()) practical_cases = practical.cases() - base_names = ['isNat?', 'lte_?', 'add', 'and?', 'not?', 'equal?', 'or?', 'contains?'] - base_trees = {name: run('arboricx', 'run', '--module', pin, '--name', 'base.' + name, - '--store', store, '--format', 'ternary').strip() for name in base_names} def compile_unit(source, environment): env_file = temp / 'environment.tree' env_file.write_bytes(bytes(map(int, ''.join('22' + of_string(name) + tree for name, tree in environment.items()) + '0'))) @@ -173,8 +175,22 @@ def main(): key, tree = pair(binding) bindings[string(key)] = tree return bindings - support_source = (HERE / 'demos/practical-support.tri').read_bytes() - support = compile_unit(support_source, base_trees) + def imported(file, target=store): + output = run('arboricx', 'import', '--file', file, '--store', target, '--indexed') + return re.search(r'Created module alias .* -> ([0-9a-f]{64})', output)[1] + native_compiler = imported(ROOT / native_metadata['bundle'], temp / 'tools') + # Source headers are authored with immutable references. Import only the + # indexed dependency pins they declare; native compilation parses/resolves. + releases = json.loads((HERE / 'packages.json').read_text())['releases'] + dependencies = set() + for name in settings: + for ref in re.findall(r'^!import ([0-9a-f]{64}) ', (HERE / 'demos' / (name + '.tri')).read_text(), re.M): + dependencies.add(ref) + for ref in sorted(dependencies): + release = next(r for r in releases if r['manifest'] == ref) + file = HERE / 'bundles' / (release['hash'] + '.arboricx') + assert digest(file.read_bytes()) == release['hash'] + assert imported(file) == ref def encode_literal(literal): kind, value = literal['type'], literal['value'] if kind == 'number': return of_number(int(value)) @@ -192,16 +208,14 @@ def main(): catalogue = [] for name, setting in settings.items(): source = (HERE / 'demos' / (name + '.tri')).read_bytes() - environment = {**base_trees, **support} if name in practical_cases else {} - bindings = compile_unit(source, environment) - rows = [] - for export in setting['exports']: - tree_pin = publish('arboricx.tree-term.v1', bytes(map(int, bindings[export]))) - rows.append(f'export\t{export}\tarboricx.tree-term.v1\t{tree_pin}\tarboricx.abi.tree.v1\n') - module_pin = publish('arboricx.module-manifest.v1', - ('arboricx.module-manifest.v1\n' + ''.join(rows)).encode()) package = temp / (name + '.arboricx') - run('arboricx', 'export', '--module', module_pin, '--store', store, '--output', package) + source_file = temp / (name + '.tri') + source_file.write_bytes(source) + run('arboricx', 'compile', '--file', source_file, '--store', store, + '--toolchain', native_compiler, '--tool-store', temp / 'tools', + '--output', package, '--compile-timeout', '110') + module_pin = imported(package) + assert set(read(package)[3]) == set(setting['exports']), name bundle = package.read_bytes() bundle_hash = digest(bundle) package_bytes[bundle_hash] = bundle @@ -262,6 +276,8 @@ def main(): 'rgb': [('invalid-first-byte', 'main [(t t) (q q) (q q)]', of_string('A channel is not a canonical byte (0-255).'))], } + bindings = {export: run('arboricx', 'run', '--module', module_pin, '--name', export, + '--store', store, '--format', 'ternary').strip() for export in setting['exports']} if name in probes else {} for label, expression, expected in probes.get(name, []): probe_source = ('q x = x x\nprobe ignored = ' + expression).encode() probe = compile_unit(probe_source, bindings)['probe'] @@ -274,9 +290,6 @@ def main(): demand_cases.append(dict(label=label, source=probe_source.decode(), program=probe, result=expected)) generated[name] = dict(demandCases=demand_cases, source=source.decode(), sourceSha256=digest(source), hash=bundle_hash, mode=setting['mode'], haskellCases=cases) - if environment: - generated[name]['supportSourceSha256'] = digest(support_source) - generated[name]['baseBindings'] = ['base.' + n for n in base_names] catalogue.append(dict(id=name, title=setting['title'], hash=bundle_hash, source=source.decode(), sourceSha256=digest(source), export=setting['export'], arguments=setting['args'], @@ -303,7 +316,7 @@ def main(): encoded = ''.join(str(b) for b in (temp / 'vector.tree').read_bytes()) apply_vectors.append(dict(program=program, argument=argument, result=encoded)) - data = dict(schema=1, backend='stable', compilerExport=args.compiler_export, + data = dict(schema=1, backend='stable', nativeCompilerSha256=native_metadata['sha256'], compilerExport=args.compiler_export, compilerBundleSha256=digest(compiler.read_bytes()), compilerManifest=pin, hostSha256=digest(host.read_bytes()), demos=generated, codecVectors=vectors, applyVectors=apply_vectors) diff --git a/ext/demo-site/src/app.ts b/ext/demo-site/src/app.ts @@ -1,3 +1,4 @@ +import { localModulesUI } from './local-modules-ui.js'; import { outputReveal } from './output-reveal.js'; import { syntaxEditor, tokenize, paintSyntax } from './syntax.js'; import { printLiteral } from './literal-input.js'; @@ -97,11 +98,28 @@ let automaticRun = false; let savedRun: Extract<ClientMessage, { type: 'run' }> | undefined; let preferredExport: string | undefined; const traceRows = new Map<number, HTMLLIElement>(); +const localModules = localModulesUI(() => { + if (!draft) return; + if (busy && operation !== 'compiling') return; + editRevision++; markPreviousResult(); + if (!busy) { dispose(); el('status').textContent = 'Changes pending'; } + queueCompile(); +}); +const exportModuleButton = el<HTMLButtonElement>('export-compiled-module'); +exportModuleButton.onclick = () => { + if (busy || !compiled || !draft || sourceEditor.value !== compiledSource || editRevision !== compiledRevision || !worker) return; + cancelIdleCompile(); operation = 'exporting'; controls(true); deadline.reset(Infinity); clock(); + el('status').textContent = 'Exporting module'; + el('compiled-module-status').textContent = 'Observing public trees; Stop is available…'; + worker.postMessage({ type: 'export-module' }); +}; function pauseClock(): void { deadline.pause(); } function clock(): void { deadline.start(); } function runClock(): void { operation = 'running'; deadline.reset(Infinity); clock(); } function controls(working: boolean): void { busy = working; + localModules.disable(busy); + exportModuleButton.disabled = busy || !draft || !compiled || sourceEditor.value !== compiledSource || editRevision !== compiledRevision; backendPicker.disabled = busy; programPicker.disabled = busy || entries.length === 0; versionPicker.disabled = busy; hashInput.disabled = busy; @@ -158,6 +176,7 @@ function clearOutput(): void { } function finish(message: string, error = false, reason: 'failure' | 'timeout' | 'cancelled' = 'failure'): void { if (error && reason === 'failure') message = operationFailure(operation, message); + if (operation === 'exporting' && draft) el('compiled-module-status').textContent = message; if (operation === 'compiling' && reason === 'failure') { dispose(); el('status').textContent = 'Compilation failed'; el('compiler-stats').textContent = 'Compilation failed; runtime discarded.'; @@ -395,6 +414,8 @@ function populatePrograms(): void { programPicker.append(demos, packages, hash); programPicker.disabled = false; } function showRelease(release?: Release): void { + el('module-import-help').hidden = release === undefined; + el('module-import-source').textContent = release ? `!import ${release.manifest} as Library` : ''; el('release-info').textContent = release ? `${release.title} · ${release.name}@${release.version} · module ${release.manifest}` : 'No named release selected. Direct bundle hashes pin the whole file.'; } programPicker.onchange = () => { @@ -491,11 +512,11 @@ function compileDraft(): void { sourceText(sourceEditor.value); const current = draftWorker(snapshot); controls(true); deadline.reset(Infinity); clock(); el('status').textContent = 'Compiling'; - el('compiler-stats').textContent = 'Loading pinned compiler and demo environment…'; + el('compiler-stats').textContent = 'Loading pinned compiler and source dependencies…'; const started = performance.now(); const activity = () => { el('compile-activity').hidden = false; el('compile-activity').textContent = `Compiling trees locally · ${Math.floor((performance.now() - started) / 1000)} seconds elapsed · Stop is available`; }; activity(); compilerTimer = setInterval(activity, 1000); - current.postMessage({ type: 'compile', source: snapshot.source, + current.postMessage({ type: 'compile', source: snapshot.source, localModules: localModules.inputs(), ...(!scratch && selected?.environment !== undefined ? { environment: selected.environment } : {}) }); } catch (error) { finish(error instanceof Error ? error.message : String(error), true); } } @@ -509,6 +530,16 @@ function draftWorker(snapshot: { revision: number; source: string }): Worker { if (worker !== current) return; if ((data.type === 'compiled' || data.type === 'error') && discardStale()) return; switch (data.type) { + case 'module-exported': { + idleDraft(); + const url = URL.createObjectURL(new Blob([new Uint8Array(data.bytes).buffer], { type: 'application/octet-stream' })); + const anchor = document.createElement('a'); anchor.href = url; anchor.download = `${data.hash}.arboricx`; + anchor.click(); URL.revokeObjectURL(url); + el('compiled-module-status').textContent = `Exported compiled module. Manifest: ${data.manifest} · Bundle SHA-256: ${data.hash}. Open the downloaded file under Local modules to import it.`; + el('status').textContent = 'Compiled'; break; + } + case 'module-export-error': + idleDraft(); el('compiled-module-status').textContent = data.message; el('status').textContent = 'Module export failed'; break; case 'compiled': stopCompilerActivity(); pauseClock(); operation = undefined; compiledSource = snapshot.source; compiledRevision = snapshot.revision; compiled = true; exportsInput.replaceChildren(); @@ -519,7 +550,7 @@ function draftWorker(snapshot: { revision: number; source: string }): Worker { el('compiler-stats').textContent = compilationStats; break; case 'state': - if (data.state === 'running') { clock(); pending = undefined; el('status').textContent = operation === 'compiling' ? 'Compiling' : 'Running'; } + if (data.state === 'running') { clock(); pending = undefined; el('status').textContent = operation === 'compiling' ? 'Compiling' : operation === 'exporting' ? 'Exporting module' : 'Running'; } else { pauseClock(); pending = { id: data.id, kind: data.state }; inputForm.hidden = data.state !== 'input'; nextButton.disabled = data.state !== 'step'; el('status').textContent = data.state === 'input' ? 'Waiting for input' : 'Paused before action'; revealOutput.reveal(data.state === 'input' ? inputForm : nextButton); } break; case 'trace': { @@ -580,14 +611,18 @@ const examples = { input: { name: 'io', source: 'io=t "tricuIO" (t 1 (t 11 t))', args: [], output: 'string', mode: 'io' }, }; for (const button of document.querySelectorAll<HTMLButtonElement>('[data-compiler-example]')) button.onclick = () => { - const example = examples[button.dataset['compilerExample'] as keyof typeof examples]; if (!example) return; + const math = packageReleases(releases, 'tricu-lib-native-math')[0]; + const example = button.dataset['compilerExample'] === 'module' && math + ? { name: 'answer', source: `!import ${math.manifest} as N\n!export answer\n\nanswer = N.add 40 2`, args: [], output: 'number', mode: 'pure' } + : examples[button.dataset['compilerExample'] as keyof typeof examples]; + if (!example) return; chooseProgram(''); revealOutput.cancel(); keepDraft(); clearOutput(); clearTreeExport(); scratch = true; draft = true; originalSource = undefined; if (!compiled) exportsInput.replaceChildren(); editRevision++; preferredName = example.name; sourceEditor.hidden = false; el('source-notes').hidden = true; sourceEditor.value = example.source; argsInput.value = JSON.stringify(example.args, null, 2); argumentsUI.refresh(true); resultCodec.value = visibleCodec(example.output); mode.value = example.mode; presetExpression(example.name); - controls(false); el('package-info').textContent = 'Scratch program · no published bundle selected.'; el('release-info').textContent = ''; el('source-label').textContent = 'Scratch program · contract helpers'; + controls(false); el('package-info').textContent = 'Scratch program · no published bundle selected.'; showRelease(); el('source-label').textContent = 'Scratch program · explicit modules or contract helpers'; el('status').textContent = 'Changes pending'; queueCompile(); }; function loadFragment(): boolean { diff --git a/ext/demo-site/src/compiler-protocol.ts b/ext/demo-site/src/compiler-protocol.ts @@ -1,7 +1,9 @@ import type { RuntimeStats } from './runtime-backends.js'; import type { OutputType } from './codecs.js'; import type { RequestId, WorkerMessage } from './protocol.js'; -export type CompilerClient = { type: 'compile'; source: unknown; environment?: string } +import type { LocalModuleInput } from './local-modules.js'; +export type CompilerClient = { type: 'compile'; source: unknown; environment?: string; localModules?: LocalModuleInput[] } + | { type: 'export-module' } | { type: 'run'; export: string; arguments: unknown; expression?: string; output: OutputType; mode: 'pure' | 'io'; step: boolean } | { type: 'resume'; id: RequestId; value?: string }; export type CompilerMessage = Exclude<WorkerMessage, { type: 'loaded' }> diff --git a/ext/demo-site/src/compiler.ts b/ext/demo-site/src/compiler.ts @@ -11,7 +11,7 @@ export function compilerDescriptor(raw: unknown): { hash: BundleHash } { export const COMPILER_COLLECTION = Object.freeze({ threshold: 250_000 }); export const SOURCE_LIMIT = 16_384; export function sourceText(source: unknown): string { - if (typeof source !== 'string' || !source.trim()) throw new Error('Enter a standalone source unit'); + if (typeof source !== 'string' || !source.trim()) throw new Error('Enter a source unit or native module'); if (source.length > SOURCE_LIMIT * 2) throw new Error('Source limit exceeded'); let count = 0; for (const char of source) { @@ -45,7 +45,7 @@ export function compilerDiagnostic(graph: Graph, payload: NodeId): string { } // Decode only the result spine/names. Compiled program trees remain lazy handles. // Do not normalize/serialize them merely to populate an export selector. -export function compiledDefinitions(graph: Graph, result: NodeId): Map<string, NodeId> { +export function compiledDefinitions(graph: Graph, result: NodeId, allowEmpty = false): Map<string, NodeId> { const [tag, payload] = graph.pair(result, 'compiler result'); const flag = graph.observe(tag).node; if (flag.kind === 'leaf') throw new Error(compilerDiagnostic(graph, payload)); @@ -58,6 +58,6 @@ export function compiledDefinitions(graph: Graph, result: NodeId): Map<string, N if (!name || exports.has(name)) throw new Error('Empty/duplicate compiled definition name'); exports.set(name, program); } - if (!exports.size) throw new Error('Source unit produced no definitions'); + if (!exports.size && !allowEmpty) throw new Error('Source unit produced no definitions'); return exports; } diff --git a/ext/demo-site/src/haskell-session.ts b/ext/demo-site/src/haskell-session.ts @@ -1,3 +1,5 @@ +import { moduleSnapshot } from './module-bundle.js'; +import type { LocalModuleInput } from './local-modules.js'; import { isTreeResult, treeResult } from './tree-result.js'; import type { GraphPreview } from './graph.js'; import { expressionUnit, expressionDiagnostic } from './expression.js'; @@ -5,11 +7,10 @@ import { expressionUnit, expressionDiagnostic } from './expression.js'; // fabricated graph statistic crosses into the shared site protocol. import { compilerDescriptor } from './compiler.js'; import { fetchBytes, type BundleHash } from './bundle.js'; -import { environmentProfile } from './packages.js'; import type { Literal, OutputType, ValueView } from './codecs.js'; import type { IOHost } from './io.js'; import type { RuntimeStats } from './runtime-backends.js'; -interface Reply { text: string; linearBytes: number; compilerHash?: string | null; } +interface Reply { text: string; linearBytes: number; compilerHash?: string | null; scopeNames?: string[]; } interface Client { disposed: boolean; request(message: object, timeout?: number | null): Promise<Reply>; @@ -42,20 +43,18 @@ export class HaskellSession { } private async json<T>(message: object): Promise<T> { return JSON.parse((await this.request(message)).text) as T; } async load(bytes: Uint8Array, hash: BundleHash): Promise<void> { this.names = await this.json<string[]>({ type: 'load', bytes: new Uint8Array(bytes).buffer, hash }); } - async compile(source: string, profileName?: string): Promise<string[]> { - let environment: { bytes: ArrayBuffer; hash: BundleHash; names: string[] } | null | undefined; - if (profileName !== undefined) { - const bytes = await fetchBytes(new URL('../environments.json', import.meta.url), 32768); - const selected = environmentProfile(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)) as unknown, profileName); - if (selected.compiler !== this.compilerHash) throw new Error('Demo environment/compiler pin mismatch'); - environment = selected.profile ? { - bytes: new Uint8Array(await fetchBytes(new URL(`/_arboricx/bundle/hash/${selected.profile.hash}`, import.meta.url))).buffer, - hash: selected.profile.hash, names: selected.profile.names, - } : null; - } - const reply = await this.request({ type: 'compile', source, ...(environment === undefined ? {} : { environment }) }); - this.names = reply.text.trimEnd().split('\n').filter(Boolean); - return this.names; + async compile(source: string, profileName?: string, localModules: LocalModuleInput[] = []): Promise<string[]> { + this.names = []; + const reply = await this.request({ type: 'compile', source, localModules, base: new URL('../', import.meta.url).href, + ...(profileName === undefined ? {} : { profileName }) }); + const names = reply.text.trimEnd().split('\n').filter(Boolean); + this.names = reply.scopeNames ?? names; + return names; + } + + async exportModule(): Promise<Uint8Array> { + const value = await this.json<{ names: string[]; snapshot: GraphPreview }>({ type: 'module-snapshot' }); + return moduleSnapshot(value.names, value.snapshot); } async run(name: string, args: Literal[], output: OutputType, mode: 'pure' | 'io', host: IOHost): Promise<ValueView> { return this.execute({ type: mode === 'pure' ? 'evaluate' : 'io-start', name, arguments: args, output }, output, mode, host); diff --git a/ext/demo-site/src/local-module-worker.ts b/ext/demo-site/src/local-module-worker.ts @@ -0,0 +1,5 @@ +import { validateLocalModule } from './local-modules.js'; +const scope = globalThis as unknown as { onmessage: ((e: MessageEvent<Uint8Array>) => void) | null; postMessage(value: unknown): void }; +scope.onmessage = ({ data }) => { + void validateLocalModule(data).then(module => scope.postMessage({ module }), error => scope.postMessage({ error: String(error) })); +}; diff --git a/ext/demo-site/src/local-modules-ui.ts b/ext/demo-site/src/local-modules-ui.ts @@ -0,0 +1,56 @@ +import { BUNDLE_LIMIT } from './bundle.js'; +import { LOCAL_MODULE_BYTES, LOCAL_MODULE_COUNT, type LocalModule, type LocalModuleInput } from './local-modules.js'; +// Hold local module files in page memory until removal or page departure. +export function localModulesUI(changed: () => void): { inputs(): LocalModuleInput[]; disable(busy: boolean): void } { + const input = document.getElementById('local-module-file') as HTMLInputElement; + const list = document.getElementById('local-module-list')!; + const status = document.getElementById('local-module-status')!; + const cancel = document.getElementById('cancel-local-module') as HTMLButtonElement; + const modules = new Map<string, { label: string; module: LocalModule }>(); + let busy = false, checking = false, abort: (() => void) | undefined; + const render = (): void => { + input.disabled = busy || checking; cancel.hidden = !checking; + list.replaceChildren(); + for (const [manifest, { label, module }] of modules) { + const row = document.createElement('li'), title = document.createElement('p'); + title.textContent = `${label} · ${module.names.length} export(s) · ${module.bytes.byteLength.toLocaleString()} bytes`; + const code = document.createElement('code'); code.textContent = `!import ${manifest} as Local`; + const details = document.createElement('details'), summary = document.createElement('summary'), names = document.createElement('p'); + summary.textContent = 'Exports and bundle hash'; names.textContent = `${module.names.join(', ')}\nBundle SHA-256: ${module.hash}`; details.append(summary, names); + const copy = document.createElement('button'); copy.textContent = 'Copy import'; + copy.onclick = () => { void (async () => { try { await navigator.clipboard.writeText(code.textContent!); status.textContent = 'Import copied.'; } catch { status.textContent = code.textContent; } })(); }; + const remove = document.createElement('button'); remove.textContent = 'Remove'; remove.dataset['removeModule'] = manifest; remove.disabled = busy || checking; + remove.onclick = () => { modules.delete(manifest); render(); status.textContent = 'Local module removed. Draft imports will be resolved again.'; changed(); }; + row.append(title, code, details, copy, remove); list.append(row); + } + }; + cancel.onclick = () => abort?.(); + input.onchange = () => { + const file = input.files?.[0]; input.value = ''; if (!file || busy || checking) return; + if (!file.size || file.size > BUNDLE_LIMIT) { status.textContent = 'Choose a nonempty .arboricx file of at most 16 MiB.'; return; } + checking = true; render(); status.textContent = 'Checking module locally…'; + void (async () => { + let worker: Worker | undefined, active = true; + let timer: ReturnType<typeof setTimeout> | undefined; + try { + const current = new Worker(new URL('./local-module-worker.js', import.meta.url), { type: 'module' }); worker = current; + const module = await new Promise<LocalModule>((resolve, reject) => { + abort = () => reject(new Error('Local file check cancelled.')); + timer = setTimeout(() => reject(new Error('Local file check timed out.')), 60_000); + current.onmessage = ({ data }: MessageEvent<{ module?: LocalModule; error?: string }>) => data.module ? resolve(data.module) : reject(new Error(data.error ?? 'Invalid local module')); + current.onerror = event => { event.preventDefault(); reject(new Error(event.message || 'Local file check failed')); }; + void file.arrayBuffer().then(bytes => { if (active) current.postMessage(new Uint8Array(bytes)); }).catch(reject); + }); + if (modules.has(module.manifest)) { status.textContent = 'This module manifest is already available locally.'; return; } + const total = [...modules.values()].reduce((n, item) => n + item.module.bytes.byteLength, module.bytes.byteLength); + if (modules.size >= LOCAL_MODULE_COUNT || total > LOCAL_MODULE_BYTES) throw new Error('Local collection limit: 32 modules / 64 MiB. Remove a module first.'); + modules.set(module.manifest, { label: file.name.slice(0, 256), module }); + status.textContent = 'Available locally by manifest hash.'; + changed(); + } catch (error) { status.textContent = String(error); } + finally { active = false; clearTimeout(timer); worker?.terminate(); abort = undefined; checking = false; render(); } + })(); + }; + render(); + return { inputs: () => [...modules.values()].map(({ module }) => ({ manifest: module.manifest, bytes: module.bytes })), disable: value => { busy = value; input.disabled = busy || checking; for (const button of list.querySelectorAll<HTMLButtonElement>('[data-remove-module]')) button.disabled = busy || checking; } }; +} diff --git a/ext/demo-site/src/local-modules.ts b/ext/demo-site/src/local-modules.ts @@ -0,0 +1,24 @@ +import { BUNDLE_LIMIT, decodeBundle, sha256, type BundleHash } from './bundle.js'; +import { moduleHash, moduleIdentity, type ModuleHash } from './module-identity.js'; +export const LOCAL_MODULE_COUNT = 32, LOCAL_MODULE_BYTES = 64 * 1024 * 1024; +export interface LocalModuleInput { manifest: string; bytes: Uint8Array; } +export interface LocalModule extends LocalModuleInput { manifest: ModuleHash; hash: BundleHash; names: string[]; } +export async function validateLocalModule(input: Uint8Array): Promise<LocalModule> { + if (!(input instanceof Uint8Array) || !input.byteLength || input.byteLength > BUNDLE_LIMIT) throw new Error('Local module must be at most 16 MiB'); + const bytes = new Uint8Array(input), bundle = decodeBundle(bytes); + return { bytes, manifest: await moduleIdentity(bundle), hash: await sha256(bytes), names: bundle.exports.map(e => e.name) }; +} +// Copy at the async boundary; verify supplied identities against these bytes. +export function localModuleInputs(input: unknown = []): LocalModuleInput[] { + if (!Array.isArray(input) || input.length > LOCAL_MODULE_COUNT) throw new Error('Local module count limit exceeded'); + let size = 0; const seen = new Set<string>(); + return input.map((entry: unknown) => { + if (!entry || typeof entry !== 'object') throw new Error('Invalid local module'); + const { manifest, bytes } = entry as LocalModuleInput; + moduleHash(manifest); + if (seen.has(manifest)) throw new Error('Duplicate local module manifest'); seen.add(manifest); + if (!(bytes instanceof Uint8Array) || !bytes.byteLength || bytes.byteLength > BUNDLE_LIMIT) throw new Error('Local module byte limit exceeded'); + size += bytes.byteLength; if (size > LOCAL_MODULE_BYTES) throw new Error('Local module collection exceeds 64 MiB'); + return { manifest, bytes: new Uint8Array(bytes) }; + }); +} diff --git a/ext/demo-site/src/module-bundle.ts b/ext/demo-site/src/module-bundle.ts @@ -0,0 +1,65 @@ +// Explicit publication boundary: snapshots observe finite constructor trees. +// Canonical indexing preserves DAG sharing. +import { BUNDLE_LIMIT, decodeBundle, type Bundle } from './bundle.js'; +import { snapshotBundle } from './tree-result.js'; +import type { GraphPreview } from './graph.js'; +const encoder = new TextEncoder(); +const join = (parts: Uint8Array[]): Uint8Array => { + const length = parts.reduce((n, p) => n + p.length, 0); + if (length > BUNDLE_LIMIT) throw new Error('Module bundle exceeds 16 MiB'); + const out = new Uint8Array(length); let at = 0; + for (const part of parts) { out.set(part, at); at += part.length; } return out; +}; +function word(n: number, size = 4): Uint8Array { + const bytes = new Uint8Array(size), view = new DataView(bytes.buffer); + if (size === 8) view.setBigUint64(0, BigInt(n)); + else if (size === 2) view.setUint16(0, n); else view.setUint32(0, n); + return bytes; +} +const string = (s: string): Uint8Array => { const bytes = encoder.encode(s); return join([word(bytes.length), bytes]); }; +export function encodeModule(bundle: Bundle): Uint8Array { + if (!bundle.exports.length || bundle.exports.length > 4096) throw new Error('Invalid module export count'); + const mapped = new Map<number, number>(), interned = new Map<string, number>(), records: number[][] = []; + for (const entry of bundle.exports) { + if (!/^[A-Za-z_][A-Za-z0-9_?$%'.-]*$/u.test(entry.name) || encoder.encode(entry.name).length > 512) throw new Error('Invalid module export name'); + const stack: [number, boolean][] = [[entry.root, false]]; + while (stack.length) { + const [id, leave] = stack.pop()!; if (mapped.has(id)) continue; + const node = bundle.nodes[id]; if (!node) throw new Error('Missing module node'); + const children = node.kind === 'leaf' ? [] : node.kind === 'stem' ? [node.child] : [node.left, node.right]; + if (children.some(c => c < 0 || c >= id)) throw new Error('Invalid module edge'); + if (!leave) { stack.push([id, true]); for (const c of [...children].reverse()) stack.push([c, false]); } + else { + const row = children.map(c => mapped.get(c)!), key = row.length + ':' + row.join(','); + let index = interned.get(key); + if (index === undefined) { index = records.length; interned.set(key, index); records.push(row); } + if (records.length > 100_000) throw new Error('Module node limit exceeded'); + mapped.set(id, index); + } + } + } + const manifest = join([encoder.encode('ARBMNFST'), word(1, 2), word(1, 2), + ...['arboricx.bundle.manifest.v1', 'tree-calculus-executable-object', 'tree-calculus.v1', 'indexed', + 'arboricx.indexed.node.v1', 'arboricx.indexed.payload.v1', 'tree-calculus.v1', 'normal-order', 'arboricx.abi.tree.v1'].map(string), + word(0), new Uint8Array([0]), word(bundle.exports.length), + ...bundle.exports.flatMap((e, i) => [word(mapped.get(e.root)!), string(i ? 'root' : 'default')]), + word(bundle.exports.length), ...bundle.exports.flatMap(e => [string(e.name), word(mapped.get(e.root)!), string('term'), string('arboricx.abi.tree.v1')]), + word(0), word(0)]); + const nodes = join([word(records.length, 8), ...records.map(row => { + const payload = join([new Uint8Array([row.length]), ...row.map(n => word(n))]); return join([word(payload.length), payload]); + })]); + const section = (type: number, at: number, size: number) => join([word(type), word(1, 2), word(1, 2), word(0), word(at, 8), word(size, 8), word(0)]); + const bytes = join([encoder.encode('ARBORICX'), word(1, 2), word(0, 2), word(2), word(0, 8), word(32, 8), + section(1, 96, manifest.length), section(2, 96 + manifest.length, nodes.length), manifest, nodes]); + decodeBundle(bytes); // Independent reader enforces the actual portable profile. + return bytes; +} +export function moduleSnapshot(names: string[], snapshot: GraphPreview): Uint8Array { + const bundle = snapshotBundle(snapshot); let spine = bundle.roots[0]!; + bundle.exports = names.map(name => { + const cell = bundle.nodes[spine]; if (cell?.kind !== 'fork') throw new Error('Invalid module snapshot spine'); + spine = cell.right; return { name, root: cell.left, kind: 'term', abi: 'arboricx.abi.tree.v1' }; + }); + if (bundle.nodes[spine]?.kind !== 'leaf') throw new Error('Invalid module snapshot tail'); + return encodeModule(bundle); +} diff --git a/ext/demo-site/src/module-identity.ts b/ext/demo-site/src/module-identity.ts @@ -0,0 +1,61 @@ +// Native indexed import identity (ContentStore.Bundle / Wire.extractBundleRoot). +// Hash stored DAG records in left-before-right physical-edge order. +import { bundleHash, sha256, type Bundle, type BundleHash } from './bundle.js'; +export type ModuleHash = string & { readonly __moduleHash: unique symbol }; +export function moduleHash(value: unknown): ModuleHash { return bundleHash(value) as string as ModuleHash; } +const utf8 = new TextEncoder(); +function join(parts: Uint8Array[]): Uint8Array { + const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0)); + let at = 0; for (const p of parts) { out.set(p, at); at += p.length; } return out; +} +function word(n: number, size = 4): Uint8Array { + const out = new Uint8Array(size), view = new DataView(out.buffer); + if (size === 8) view.setBigUint64(0, BigInt(n)); + else if (size === 2) view.setUint16(0, n); else view.setUint32(0, n); + return out; +} +const string = (s: string): Uint8Array => { const b = utf8.encode(s); return join([word(b.length), b]); }; +export function indexedObject(bundle: Bundle, root: number): Uint8Array { + const ids = new Map<number, number>(), rows: Uint8Array[] = [], stack: [number, boolean][] = [[root, false]]; + while (stack.length) { + const [id, leave] = stack.pop()!; + if (ids.has(id)) continue; + const node = bundle.nodes[id]; if (!node) throw new Error('Missing indexed node'); + const children = node.kind === 'leaf' ? [] : node.kind === 'stem' ? [node.child] : [node.left, node.right]; + if (children.some(c => c >= id || c < 0)) throw new Error('Invalid indexed edge'); + if (!leave) { stack.push([id, true]); for (const c of children.reverse()) stack.push([c, false]); } + else { + const payload = join([new Uint8Array([children.length]), ...children.map(c => word(ids.get(c)!))]); + ids.set(id, rows.length); rows.push(join([word(payload.length), payload])); + } + } + const index = ids.get(root)!; + const manifest = join([ + utf8.encode('ARBMNFST'), word(1, 2), word(1, 2), + ...['arboricx.bundle.manifest.v1', 'tree-calculus-executable-object', 'tree-calculus.v1', 'indexed', + 'arboricx.indexed.node.v1', 'arboricx.indexed.payload.v1', 'tree-calculus.v1', 'normal-order', 'arboricx.abi.tree.v1'].map(string), + word(0), new Uint8Array([0]), word(1), word(index), string('default'), + word(1), string('root'), word(index), string('term'), string('arboricx.abi.tree.v1'), + word(1), word(5, 2), string('arboricx'), word(0), + ]); + const nodes = join([word(rows.length, 8), ...rows]); + const section = (type: number, at: number, size: number): Uint8Array => join([ + word(type), word(1, 2), word(1, 2), word(0, 2), word(0, 2), word(at, 8), word(size, 8), word(0), + ]); + return join([utf8.encode('ARBORICX'), word(1, 2), word(0, 2), word(2), word(0, 8), word(32, 8), + section(1, 96, manifest.length), section(2, 96 + manifest.length, nodes.length), manifest, nodes]); +} +export async function moduleIdentity(bundle: Bundle): Promise<ModuleHash> { + if (!bundle.exports.length || bundle.exports.some(e => !/^[A-Za-z_][A-Za-z0-9_?$%'.-]*$/u.test(e.name))) { + throw new Error('Package requires a nonempty native module interface'); + } + const hashes = new Map<number, BundleHash>(); + let manifest = 'arboricx.module-manifest.v1\n'; + const escape = (s: string): string => s.replace(/%/g, '%25').replace(/\t/g, '%09').replace(/\n/g, '%0A').replace(/\r/g, '%0D'); + for (const e of bundle.exports) { + let hash = hashes.get(e.root); + if (!hash) { hash = await sha256(join([utf8.encode('arboricx.indexed-tree.v1\0'), indexedObject(bundle, e.root)])); hashes.set(e.root, hash); } + manifest += `export\t${escape(e.name)}\tarboricx.indexed-tree.v1\t${hash}\t${e.abi}\n`; + } + return moduleHash(await sha256(utf8.encode('arboricx.module-manifest.v1\0' + manifest))); +} diff --git a/ext/demo-site/src/module-resolver.ts b/ext/demo-site/src/module-resolver.ts @@ -0,0 +1,12 @@ +// Resolve indexed immutable manifests and verify their transport and module pins. +import { fetchBundle, type Bundle } from './bundle.js'; +import { moduleHash, moduleIdentity } from './module-identity.js'; +import type { Release } from './packages.js'; +export async function fetchModule(base: URL, reference: unknown, releases: readonly Release[]): Promise<Bundle> { + const manifest = moduleHash(reference); + const release = releases.find(r => (r.manifest as string) === manifest); + if (!release) throw new Error(`Unknown module manifest ${manifest}`); + const bundle = await fetchBundle(new URL(`/_arboricx/bundle/hash/${release.hash}`, base), release.hash); + if (await moduleIdentity(bundle) !== manifest) throw new Error('Module manifest mismatch'); + return bundle; +} diff --git a/ext/demo-site/src/module-stage.ts b/ext/demo-site/src/module-stage.ts @@ -0,0 +1,74 @@ +// Decode the pinned native compiler's header API. +import type { Graph, NodeId } from './graph.js'; +import { readList, readText, text } from './codecs.js'; +import { compilerDiagnostic, SOURCE_LIMIT } from './compiler.js'; +import { fetchBytes, decodeBundle, type Bundle } from './bundle.js'; +import { packageIndex } from './packages.js'; +import { localModuleInputs, validateLocalModule, type LocalModuleInput } from './local-modules.js'; +import { fetchModule } from './module-resolver.js'; +export interface ModuleStage { + body: string; + imports: [string, string][]; // immutable reference, qualifier (or *) + exports: [string, string][]; // local name/*, or from + immutable reference + native: boolean; +} +export function stageModule(graph: Graph, library: Map<string, NodeId>, source: string): ModuleStage { + const call = (name: string, argument: NodeId): NodeId => { + const f = library.get('source_module.' + name); + if (f === undefined) throw new Error('Missing native module compiler helper'); + return graph.apply(f, [argument]); + }; + const value = (result: NodeId, diagnostic = false): NodeId => { + const [tag, payload] = graph.pair(result), flag = graph.observe(tag).node; + if (flag.kind === 'leaf') throw new Error(diagnostic ? compilerDiagnostic(graph, payload) : readText(graph, graph.pair(payload)[0], 512)); + if (flag.kind !== 'stem' || graph.observe(flag.child).node.kind !== 'leaf') throw new Error('Invalid native module result'); + return graph.pair(payload)[0]; + }; + const [edges, rest] = graph.pair(value(call('sourceModuleHeaderStage', text(graph, source, SOURCE_LIMIT)), true)); + if (readList(graph, edges, SOURCE_LIMIT).length) throw new Error('Browser modules require manifest hashes; workspace and build-only sources are unavailable'); + const [uses, tail] = graph.pair(rest), [exports, body] = graph.pair(tail); + const shapes = (rows: NodeId, helper: string): [string, string][] => readList(graph, rows, SOURCE_LIMIT).map(row => { + const [a, b] = graph.pair(value(call(helper, row))); + return [readText(graph, a, 128), readText(graph, b, 128)]; + }); + const imports = shapes(uses, 'sourceModuleUseShape'), selected = shapes(exports, 'sourceModuleExportShape'); + return { body: readText(graph, body, SOURCE_LIMIT), imports, exports: selected, native: !!(imports.length || selected.length) }; +} +export async function moduleDependencies(base: URL, stage: ModuleStage, local: LocalModuleInput[] = []): Promise<Map<string, Bundle>> { + const refs = [...new Set([...stage.imports.map(i => i[0]), ...stage.exports.filter(e => e[0] === 'from').map(e => e[1])])]; + const result = new Map<string, Bundle>(); + if (!refs.length) return result; + const available = new Map(localModuleInputs(local).map(entry => [entry.manifest, entry])); + let index: ReturnType<typeof packageIndex> | undefined; + for (const ref of refs) { + const entry = available.get(ref); + if (entry) { + const checked = await validateLocalModule(entry.bytes); + if (checked.manifest !== ref) throw new Error('Local module manifest mismatch'); + result.set(ref, decodeBundle(checked.bytes)); + } else { + index ??= packageIndex(JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(await fetchBytes(new URL('packages.json', base), 2_097_152))) as unknown); + result.set(ref, await fetchModule(base, ref, index)); + } + } + return result; +} +// Projection of already native-parsed export requests onto backend-owned trees. +// Keep executable trees as backend-owned handles during interface selection. +export function selectModuleExports<T>(stage: ModuleStage, locals: Map<string, T>, modules: Map<string, Map<string, T>>): Map<string, T> { + const selected = new Map<string, T>(); + const add = (name: string, tree: T): void => { + if (selected.has(name)) throw new Error('duplicate export'); + if (selected.size >= 4096) throw new Error('Module export limit exceeded'); + selected.set(name, tree); + }; + for (const [name, ref] of stage.exports) { + if (name === 'from') { + const values = modules.get(ref); if (!values) throw new Error('Missing re-export dependency'); + for (const [key, value] of values) add(key, value); + } else if (name === '*') { for (const [key, value] of locals) add(key, value); } + else { if (!locals.has(name)) throw new Error('undeclared local export'); add(name, locals.get(name)!); } + } + if (!selected.size) throw new Error('module requires an export'); + return selected; +} diff --git a/ext/demo-site/src/protocol.ts b/ext/demo-site/src/protocol.ts @@ -15,7 +15,9 @@ export type ClientMessage = { type: 'load'; hash: BundleHash; localId?: string } | { type: 'download' } | { type: 'export'; export: string; format: TreeFormat } | { type: 'resume'; id: RequestId; value?: string }; -export type WorkerMessage = { type: 'state'; state: 'running' } +export type WorkerMessage = { type: 'module-exported'; bytes: Uint8Array; hash: BundleHash; manifest: string } + | { type: 'module-export-error'; message: string } + | { type: 'state'; state: 'running' } | { type: 'state'; state: 'input' | 'step'; id: RequestId } | { type: 'loaded'; hash: BundleHash; exports: ExportInfo[]; nodes: number; metadata: Record<string, string>; source: string | null } | { type: 'trace'; phase: 'before'; event: Trace } diff --git a/ext/demo-site/src/runtime-session.ts b/ext/demo-site/src/runtime-session.ts @@ -1,3 +1,4 @@ +import type { LocalModuleInput } from './local-modules.js'; import { HaskellSession } from './haskell-session.js'; import type { BundleHash } from './bundle.js'; import type { Literal, OutputType, ValueView } from './codecs.js'; @@ -9,7 +10,8 @@ import type { RuntimeStats } from './runtime-backends.js'; export interface RuntimeSession { readonly disposed: boolean; load(bytes: Uint8Array, hash: BundleHash): Promise<void>; - compile(source: string, profileName?: string): Promise<string[]>; + compile(source: string, profileName?: string, localModules?: LocalModuleInput[]): Promise<string[]>; + exportModule(): Promise<Uint8Array>; run(name: string, args: Literal[], output: OutputType, mode: 'pure' | 'io', host: IOHost): Promise<ValueView>; runExpression(source: string, output: OutputType, mode: 'pure' | 'io', host: IOHost): Promise<ValueView>; stats(): RuntimeStats; diff --git a/ext/demo-site/src/wasm-worker.ts b/ext/demo-site/src/wasm-worker.ts @@ -1,3 +1,4 @@ +import { localModuleInputs, validateLocalModule } from './local-modules.js'; import { resumeValue } from './io.js'; import { createRuntimeSession, type RuntimeSession } from './runtime-session.js'; const selectedBackend = new URL(globalThis.location.href).searchParams.get('backend'); @@ -46,8 +47,13 @@ scope.onmessage = ({ data }) => { if (profile !== undefined && (typeof profile !== 'string' || profile.length > 128)) throw new Error('Invalid demo environment'); running(); const start = performance.now(); session = await createRuntimeSession(selectedBackend, true); - const names = await session.compile(source, profile); + const names = await session.compile(source, profile, localModuleInputs(m['localModules'])); send({ type: 'compiled', names, stats: session.stats(), milliseconds: performance.now() - start }); + } else if (m['type'] === 'export-module') { + if (!session || stored) throw new Error('Compile a draft first'); + running(); + try { const module = await validateLocalModule(await session.exportModule()); send({ type: 'module-exported', bytes: module.bytes, hash: module.hash, manifest: module.manifest }); } + catch (e) { if (session.disposed) throw e; send({ type: 'module-export-error', message: String(e) }); } } else if (m['type'] === 'run') { if (!session) throw new Error('Load or compile first'); if (typeof m['export'] !== 'string' || m['export'].length > 512) throw new Error('Invalid export'); diff --git a/ext/demo-site/style.css b/ext/demo-site/style.css @@ -27,3 +27,7 @@ /* Keep the expression, explicit action, and result in one reading column. */ .expression-dock .output-toolbar{margin-bottom:18px}.evaluation-actions{display:flex;gap:8px;align-items:center;margin-top:14px}.output-panel #output-provenance{margin-top:0} @media(max-width:740px){.editor-toolbar #status{flex:1 1 100px;order:3;align-self:center}.evaluation-actions #run{flex:1}.evaluation-actions button{min-height:48px}} + +#local-modules code, #local-modules p { overflow-wrap: anywhere; } +#local-module-list { padding-left: 1.2rem; } +#local-module-list li { margin-bottom: 1rem; } diff --git a/ext/demo-site/test/backend-browser.mjs b/ext/demo-site/test/backend-browser.mjs @@ -53,7 +53,7 @@ try { return result.result.value; }; for(let i=0;!await evaluate(`location.href===${JSON.stringify(url)} && document.readyState==='complete'`);i++){if(i>400)throw Error('Page did not load');await new Promise(r=>setTimeout(r,25));} - const report=await evaluate(`import(${JSON.stringify(process.env.TEST_IDE?'/ide-probe.mjs':process.env.TEST_LIVE_UX?'/live-ux-probe.mjs':process.env.TEST_BENCHMARK?'/backend-benchmark.mjs':'/backend-probe.mjs')}).then(m=>m.run(${JSON.stringify(control)},${JSON.stringify(process.env.TEST_BACKEND||'haskell-wasm')},${!!process.env.BENCHMARK_PSS}))`); + const report=await evaluate(`import(${JSON.stringify(process.env.TEST_LOCAL_MODULES?'/local-module-probe.mjs':process.env.TEST_MODULES?'/module-probe.mjs':process.env.TEST_IDE?'/ide-probe.mjs':process.env.TEST_LIVE_UX?'/live-ux-probe.mjs':process.env.TEST_BENCHMARK?'/backend-benchmark.mjs':'/backend-probe.mjs')}).then(m=>m.run(${JSON.stringify(control)},${JSON.stringify(process.env.TEST_BACKEND||'haskell-wasm')},${!!process.env.BENCHMARK_PSS}))`); assert.deepEqual(exceptions,[]); if(process.env.TEST_LIVE_UX||process.env.TEST_IDE){ for(const width of [320,390,1440]){ diff --git a/ext/demo-site/test/backend-probe.mjs b/ext/demo-site/test/backend-probe.mjs @@ -62,7 +62,7 @@ export async function run(control, selectedBackend='haskell-wasm') { assert.equal(document.getElementById('run').disabled,true,'Unapplied edits cannot run old definitions'); await wait(status('Compiled'));await click('run');await wait(status('Finished'));assert.equal(await evaluate("document.getElementById('result').textContent"),'43'); await click('restore-source');await wait(status('Ready')); - // A practical draft exercises selected environment bytes/pin/name resolution. + // A practical draft exercises explicit library bytes/pins/native name resolution. await select('shipping');await evaluate("document.getElementById('source-editor').value+='\\n-- adapter test';document.getElementById('source-editor').dispatchEvent(new Event('input'))"); await click('compile');await wait(status('Compiled'));await click('run');await wait(status('Finished')); // Scratch compilation selects the runtime's authenticated default environment. diff --git a/ext/demo-site/test/backend-server.mjs b/ext/demo-site/test/backend-server.mjs @@ -7,7 +7,7 @@ import {fixtures} from './zig-negative-fixtures.mjs'; export async function startSiteServer(directory,autoRun=false) { const root=resolve(process.env.ARBORICX_SITE_ROOT||'ext/demo-site'),runtime=resolve(directory),registry=resolve('ext/demo-site/bundles'); const control='/test-'+randomBytes(24).toString('hex'),requests=[],marks=[]; - let failRuntime=false,compilerMismatch=false,deliver,fail; + let failRuntime=false,compilerMismatch=false,moduleMissing=null,moduleCorrupt=null,moduleManifest=null,deliver,fail; const completion=new Promise((resolve,reject)=>{deliver=resolve;fail=reject;});completion.catch(()=>{}); const server=createServer(async(req,res)=>{ try { @@ -19,17 +19,23 @@ export async function startSiteServer(directory,autoRun=false) { let text='';for await(const chunk of req){text+=chunk;if(text.length>262144)throw Error('control size');} const data=JSON.parse(text); if(path.endsWith('/phase'))marks.push({name:data.name,at:performance.now()}); - else if(path.endsWith('/fault')){failRuntime=data.runtime??failRuntime;compilerMismatch=data.compilerPin??compilerMismatch;} + else if(path.endsWith('/fault')){failRuntime=data.runtime??failRuntime;compilerMismatch=data.compilerPin??compilerMismatch; + if('moduleMissing' in data)moduleMissing=data.moduleMissing; + if('moduleCorrupt' in data)moduleCorrupt=data.moduleCorrupt; + if('moduleManifest' in data)moduleManifest=data.moduleManifest;} else {data.ok?deliver(data.report):fail(Error(data.error));} res.end('ok');return; } if(path==='/zig-negative.json'){res.setHeader('Content-Type','application/json');res.end(JSON.stringify(fixtures()));return;} - if(path==='/zig-fixtures.json'){res.setHeader('Content-Type','application/json');res.end(await readFile(new URL('../demos.json',import.meta.url)));return;} + if(path==='/zig-fixtures.json'){res.setHeader('Content-Type','application/json');const data=JSON.parse(await readFile(new URL('../demos.json',import.meta.url)));for(const id of ['parser','lexer'])data.demos[id]=JSON.parse(await readFile(new URL('../'+id+'-demo.json',import.meta.url)));res.end(JSON.stringify(data));return;} if(path==='/zig-session-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./zig-session-probe.mjs',import.meta.url)));return;} if(path==='/backend-resume-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./backend-resume-probe.mjs',import.meta.url)));return;} if(path==='/backend-benchmark.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./backend-benchmark.mjs',import.meta.url)));return;} if(path==='/evaluation-layout-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./evaluation-layout-probe.mjs',import.meta.url)));return;} if(path==='/syntax-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./syntax-probe.mjs',import.meta.url)));return;} + if(path==='/local-module-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./local-module-probe.mjs',import.meta.url)));return;} + if(path==='/module-goldens.json'){res.setHeader('Content-Type','application/json');res.end(await readFile(new URL('./module-goldens.json',import.meta.url)));return;} + if(path==='/module-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./module-probe.mjs',import.meta.url)));return;} if(path==='/ide-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./ide-probe.mjs',import.meta.url)));return;} if(path==='/live-ux-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./live-ux-probe.mjs',import.meta.url)));return;} if(path==='/backend-probe.mjs'){res.setHeader('Content-Type','text/javascript');res.end(await readFile(new URL('./backend-probe.mjs',import.meta.url)));return;} @@ -38,9 +44,15 @@ export async function startSiteServer(directory,autoRun=false) { const descriptor=JSON.parse(await readFile(resolve(root,'compiler.json'))); res.setHeader('Content-Type','application/json');res.end(JSON.stringify({...descriptor,hash:'0'.repeat(64)}));return; } + if(moduleManifest&&path==='/nested/site/packages.json'){ + const index=JSON.parse(await readFile(resolve(root,'packages.json'))); + const other=index.releases.find(r=>r.name==='tricu-lib-packages-io'); + index.releases=index.releases.map(r=>r.manifest===moduleManifest?{...r,hash:other.hash}:r); + res.setHeader('Content-Type','application/json');res.end(JSON.stringify(index));return; + } let file; if(path.startsWith('/_arboricx/bundle/hash/')) { - const hash=path.split('/').at(-1);if(!/^[a-f0-9]{64}$/.test(hash))throw Error('hash');file=resolve(registry,hash+'.arboricx'); + const hash=path.split('/').at(-1);if(!/^[a-f0-9]{64}$/.test(hash))throw Error('hash');if(hash===moduleMissing)throw Error('Missing module');file=resolve(registry,hash+'.arboricx'); } else { const prefix='/nested/site/';if(!path.startsWith(prefix))throw Error('mount'); const relative=path.slice(prefix.length),base=relative.startsWith('runtime/haskell/')?runtime:root; @@ -49,8 +61,9 @@ export async function startSiteServer(directory,autoRun=false) { } res.setHeader('Content-Type',({'.html':'text/html','.js':'text/javascript','.mjs':'text/javascript','.wasm':'application/wasm','.json':'application/json','.css':'text/css'})[extname(file)]??'application/octet-stream'); let bytes=await readFile(file); - if(autoRun&&path==='/nested/site/index.html')bytes=Buffer.from(bytes.toString()+`<script type="module"> - try{const m=await import(${JSON.stringify(process.env.TEST_IDE?'/ide-probe.mjs':process.env.TEST_LIVE_UX?'/live-ux-probe.mjs':process.env.TEST_BENCHMARK?'/backend-benchmark.mjs':'/backend-probe.mjs')});const report=await m.run(${JSON.stringify(control)},${JSON.stringify(process.env.TEST_BACKEND||'haskell-wasm')},${!!process.env.BENCHMARK_PSS});await fetch(${JSON.stringify(control+'/report')},{method:'POST',body:JSON.stringify({ok:true,report})});} + if(moduleCorrupt&&path==='/_arboricx/bundle/hash/'+moduleCorrupt){bytes=Buffer.from(bytes);bytes[0]^=1;} + if(autoRun&&path==='/nested/site/index.html'&&!new URL(req.url,'http://localhost').searchParams.has('noProbe'))bytes=Buffer.from(bytes.toString()+`<script type="module"> + try{const m=await import(${JSON.stringify(process.env.TEST_LOCAL_MODULES?'/local-module-probe.mjs':process.env.TEST_MODULES?'/module-probe.mjs':process.env.TEST_IDE?'/ide-probe.mjs':process.env.TEST_LIVE_UX?'/live-ux-probe.mjs':process.env.TEST_BENCHMARK?'/backend-benchmark.mjs':'/backend-probe.mjs')});const report=await m.run(${JSON.stringify(control)},${JSON.stringify(process.env.TEST_BACKEND||'haskell-wasm')},${!!process.env.BENCHMARK_PSS});await fetch(${JSON.stringify(control+'/report')},{method:'POST',body:JSON.stringify({ok:true,report})});} catch(e){await fetch(${JSON.stringify(control+'/report')},{method:'POST',body:JSON.stringify({ok:false,error:String(e.stack||e)})});} </script>`); res.end(bytes); diff --git a/ext/demo-site/test/draft-session.test.mjs b/ext/demo-site/test/draft-session.test.mjs @@ -21,6 +21,6 @@ test('source remains editable without autosave or recovery controls',async()=>{ assert.match(html,new RegExp(`id="${id}"`)); assert.doesNotMatch(html,/id="edit-source"|id="compiler-disclosure"/); const readme=await readFile(new URL('../README.md',import.meta.url),'utf8'); - assert.match(readme,/Drafts exist only in the open page/); - assert.match(readme,/page reload\s+starts fresh/); + assert.match(readme,/Draft source lives in the open page/); + assert.match(readme,/Reloading starts fresh/); }); diff --git a/ext/demo-site/test/editable-conformance.mjs b/ext/demo-site/test/editable-conformance.mjs @@ -1,4 +1,4 @@ -// Opt-in real demo compilation against pinned prebaked environments. No host +// Opt-in real demo compilation with explicit native manifest imports. No host // recompilation; expected results are retained independent Haskell captures. import assert from 'node:assert/strict'; import {readFile} from 'node:fs/promises'; @@ -6,8 +6,9 @@ import {createHash} from 'node:crypto'; import {Graph} from '../dist/graph.js'; import {decodeBundle,loadBundle,COMPILER_BUNDLE_LIMIT} from '../dist/bundle.js'; import {compiledDefinitions,sourceLiteral,COMPILER_EXPORT} from '../dist/compiler.js'; -import {environmentProfile} from '../dist/packages.js'; -import {list,text} from '../dist/codecs.js'; +import {stageModule,selectModuleExports} from '../dist/module-stage.js'; +import {moduleIdentity} from '../dist/module-identity.js'; +import {list,text,readText} from '../dist/codecs.js'; import {runIO} from '../dist/io.js'; const root=new URL('../',import.meta.url); const catalogue=JSON.parse(await readFile(new URL('catalogue.json',root))); @@ -18,17 +19,36 @@ async function bundle(hash,limit){ assert.equal(createHash('sha256').update(bytes).digest('hex'),hash); return decodeBundle(bytes,limit); } +for(const id of ['parser','lexer'])goldens.demos[id]=JSON.parse(await readFile(new URL(id+'-demo.json',root))); +const releases=JSON.parse(await readFile(new URL('packages.json',root))).releases; const compiler=await bundle(environments.compiler,COMPILER_BUNDLE_LIMIT); for(const entry of catalogue.filter(e=>!process.argv[2]||e.id===process.argv[2])){ const started=performance.now(); const g=new Graph({nodes:6_000_000,fuel:Infinity,stack:100_000},{threshold:250_000}); - const library=loadBundle(g,compiler), {profile}=environmentProfile(environments,entry.environment); - const bindings=[]; - if(profile){ - const support=loadBundle(g,await bundle(profile.hash)); - for(const name of profile.names){assert.ok(support.has(name));bindings.push(g.fork(text(g,name),support.get(name)));} + const library=loadBundle(g,compiler),stage=stageModule(g,library,entry.source+'\n-- Edited locally\n'); + assert.ok(stage.native); + // Header strings/shapes now live in JS; release native parsing temporaries. + g.collect(library.values()); + const modules=new Map(),scope=new Map(); + const roots=()=>[...library.values(),...[...modules.values()].flatMap(m=>[...m.values()])]; + let qualifiedCount=0; + for(const [ref,qualifier] of stage.imports){ + if(!modules.has(ref)){ + const release=releases.find(r=>r.manifest===ref);assert.ok(release); + const decoded=await bundle(release.hash);assert.equal(await moduleIdentity(decoded),ref); + modules.set(ref,loadBundle(g,decoded)); + } + for(const [name,value] of modules.get(ref)){ + const qualified=readText(g,g.apply(library.get('source_module.sourceModuleQualified'),[text(g,qualifier),text(g,name)]),512); + assert.ok(!scope.has(qualified));scope.set(qualified,value); + if(++qualifiedCount%32===0)g.collect(roots()); + } } - const definitions=compiledDefinitions(g,g.apply(library.get(COMPILER_EXPORT),[list(g,bindings),sourceLiteral(g,entry.source+'\n-- Edited locally\n')])); + g.collect(roots()); + const bindings=[...scope].map(([name,value])=>g.fork(text(g,name),value)); + const locals=compiledDefinitions(g,g.apply(library.get(COMPILER_EXPORT),[list(g,bindings),sourceLiteral(g,stage.body)])); + for(const name of locals.keys())assert.ok(!scope.has(name)); + const definitions=selectModuleExports(stage,locals,modules); g.collect(definitions.values()); console.log(entry.id,'compile ms',Math.round(performance.now()-started),'stats',JSON.stringify(g.stats)); // Exactly apply the default published export using the first Haskell capture diff --git a/ext/demo-site/test/local-module-native.py b/ext/demo-site/test/local-module-native.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""Verify browser-produced exports with the native CLI and shipped compiler. + +Input is a local-module browser probe JSON report (BENCHMARK_REPORT). +Expected identities come from independent native compilation using a Nix-built host. +""" +import argparse +import json +from pathlib import Path +import re +import subprocess +import sys +import tempfile +ROOT = Path(__file__).resolve().parents[3] +SITE = ROOT / 'ext/demo-site' +sys.path.insert(0, str(ROOT / 'test')) +from shipped_compiler import verify +from bundle_dag import read + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('tricu', type=Path) + parser.add_argument('reports', nargs='+', type=Path) + args = parser.parse_args() + metadata = verify() + releases = json.loads((SITE / 'packages.json').read_text())['releases'] + identities = set() + with tempfile.TemporaryDirectory(prefix='tricu-local-export-') as temporary: + work = Path(temporary) + (work / 'tricu.workspace').write_text('tricu.workspace.v1\n') + def run(*words): + reply = subprocess.run([str(args.tricu.resolve()), *map(str, words), '+RTS', '-N1', '-M2048m', '-RTS'], + cwd=work, capture_output=True, timeout=120) + assert reply.returncode == 0, (reply.stdout + reply.stderr).decode() + return reply.stdout.decode().strip() + def imported(file, store): + return re.search(r'Created module alias .* -> ([0-9a-f]{64})', run('arboricx', 'import', '--indexed', '--file', file, '--store', store))[1] + compiler = imported(ROOT / metadata['bundle'], work / 'tools') + for report in args.reports: + data = json.loads(report.read_text()) + file = work / 'browser.arboricx' + file.write_bytes(bytes(data['bytes'])) + manifest = imported(file, work / 'consumer') + assert manifest == data['manifest'] + assert list(read(file)[3]) == ['echo', 'plus', 'value'] + def natural(n): return (b'\x02' + (b'\x01\x00' if n % 2 else b'\x00') + natural(n // 2)) if n else b'\x00' + for name, number, expected in [('plus', 33, '42'), ('value', None, '42'), ('echo', 17, '17')]: + arguments = [] + if number is not None: + arg = work / 'argument.tree'; arg.write_bytes(natural(number)) + arguments = ['--arg-tree-file', arg] + assert run('arboricx', 'run', '--module', manifest, '--store', work / 'consumer', '--name', name, *arguments, '--format', 'number') == expected + for ref in re.findall(r'^!import ([0-9a-f]{64}) ', data['source'], re.M): + release = next(r for r in releases if r['manifest'] == ref) + assert imported(SITE / 'bundles' / (release['hash'] + '.arboricx'), work / 'build') == ref + source = work / 'original.tri'; source.write_text(data['source']) + native = work / 'native.arboricx' + run('arboricx', 'compile', '--file', source, '--store', work / 'build', '--toolchain', compiler, + '--tool-store', work / 'tools', '--output', native, '--compile-timeout', '110') + assert imported(native, work / 'native-consumer') == manifest, 'Native compiled interface/tree identities differ' + identities.add(manifest) + assert len(identities) == 1, 'Backend export identities differ' + print('Native import/run and independently compiled complete module identity agree for', len(args.reports), 'browser reports') + + +if __name__ == '__main__': + main() diff --git a/ext/demo-site/test/local-module-probe.mjs b/ext/demo-site/test/local-module-probe.mjs @@ -0,0 +1,94 @@ +const assert=(ok,message)=>{if(!ok)throw Error(message);}; +const equal=(a,b,message)=>assert(JSON.stringify(a)===JSON.stringify(b),message+': '+JSON.stringify(a)); +async function rejects(fn,pattern){try{await fn();}catch(e){assert(pattern.test(String(e)),'Wrong rejection: '+e);return;}throw Error('Expected rejection');} +const el=id=>document.getElementById(id),delay=ms=>new Promise(r=>setTimeout(r,ms)); +async function wait(fn){for(let i=0;i<4500;i++){if(fn())return;await delay(20);}throw Error('Timed out: '+el('status').textContent+' / '+el('compiled-module-status').textContent);} +const status=s=>wait(()=>el('status').textContent===s); +const input=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('input'));}; +const change=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('change'));}; +export async function run(control,backend){ + const base=new URL('/nested/site/',location.href); + const {createRuntimeSession}=await import(new URL('dist/runtime-session.js',base)); + const {validateLocalModule}=await import(new URL('dist/local-modules.js',base)); + const {encodeModule}=await import(new URL('dist/module-bundle.js',base)); + const {decodeBundle}=await import(new URL('dist/bundle.js',base)); + const index=await(await fetch(new URL('packages.json',base))).json(); + const math=index.releases.find(r=>r.name==='tricu-lib-native-math'&&r.version==='0.1.0'); + const source=`!import ${math.manifest} as N\n!export echo\n!export plus\n!export value\nprivate = 9\necho x = x\nplus x = N.add x private\nvalue = 42\nq x = x x\nhidden = q q`; + const host={before:async()=>{},after:()=>{},read:async()=>'',write:()=>{},running:()=>{}}; + const s=await createRuntimeSession(backend,true);let exported; + try{ + await s.compile(source); + exported=await validateLocalModule(await s.exportModule()); + equal(exported.names,['echo','plus','value'],'Only public exports, no imports/private divergent value'); + equal((await s.runExpression('N.add value private','number','pure',host)).value,'51','Export preserves expression scope'); + const start=(await(await fetch(control+'/requests')).json()).length; + await s.compile(`!import ${exported.manifest} as L\n!export answer\nanswer = L.plus 33`,undefined,[exported]); + equal((await s.runExpression('L.echo answer','number','pure',host)).value,'42','Local qualified import'); + await s.compile(`!import ${exported.manifest} *\n!export answer\nanswer = plus 33`,undefined,[exported]); + equal((await s.run('answer',[],'number','pure',host)).value,'42','Local open import'); + await s.compile(`!export * from ${exported.manifest}`,undefined,[exported]); + equal((await validateLocalModule(await s.exportModule())).manifest,exported.manifest,'Full reexport preserves native identity'); + const requests=(await(await fetch(control+'/requests')).json()).slice(start); + assert(!requests.some(p=>p.endsWith('/packages.json')||p.startsWith('/_arboricx/')),'Local resolution performs no registry requests'); + const corrupt=exported.bytes.slice();corrupt[0]^=1; + await rejects(()=>s.compile(`!import ${exported.manifest} *\n!export value`,undefined,[{...exported,bytes:corrupt}]),/magic/); + await rejects(()=>s.exportModule(),/No compiled module/); + const bindings=['x0 = t t t'];for(let i=1;i<=30;i++)bindings.push(`x${i} = t x${i-1} x${i-1}`); + await s.compile('!export deep\n!export alias\ndeep = (let\n '+bindings.join('\n ')+'\n in x30)\nalias = deep'); + const shared=decodeBundle(await s.exportModule()); + assert(shared.nodes.length<40,'Export preserves exponential sharing'); + equal(shared.exports[0].root,shared.exports[1].root,'Cross-export sharing preserved'); + const original=decodeBundle(exported.bytes),names=Array.from({length:24},(_,i)=>'entry'+i); + const wide=await validateLocalModule(encodeModule({...original,exports:names.map(name=>({...original.exports[0],name}))})); + equal(await s.compile(`!export * from ${wide.manifest}`,undefined,[wide]),names,'Local public interface is not capped at 16 definitions'); + equal((await validateLocalModule(await s.exportModule())).manifest,wide.manifest,'All 24 reexports survive portable export'); + + await s.compile('!export action\naction = t "tricuIO" (t 1 (t 20 "file"))'); + const capability=await validateLocalModule(await s.exportModule()); + await s.compile(`!import ${capability.manifest} as L\n!export main\nmain = L.action`,undefined,[capability]); + await rejects(()=>s.run('main',[],'string','io',host),/Unsupported|unsupported/); + + }finally{s.dispose();} + await status('Ready');change('runtime-backend',backend);await status('Ready'); + document.querySelector('[data-compiler-example=module]').click();await status('Compiled'); + input('source-editor',source);el('compile').click();await status('Compiled'); + const createURL=URL.createObjectURL,click=HTMLAnchorElement.prototype.click;let downloaded,name; + URL.createObjectURL=blob=>{downloaded=blob;return createURL(blob);};HTMLAnchorElement.prototype.click=function(){name=this.download;}; + try{ + el('export-compiled-module').click();await wait(()=>downloaded&&el('status').textContent==='Compiled'); + }finally{URL.createObjectURL=createURL;HTMLAnchorElement.prototype.click=click;} + const file=await validateLocalModule(new Uint8Array(await downloaded.arrayBuffer())); + equal(file.manifest,exported.manifest,'Actual-page download contains compiled public interface'); + equal(name,file.hash+'.arboricx','Download named by bundle hash'); + const select=bytes=>{const transfer=new DataTransfer();transfer.items.add(new File([bytes],'<svg onload=bad>.arboricx'));el('local-module-file').files=transfer.files;el('local-module-file').dispatchEvent(new Event('change'));}; + select(file.bytes);await wait(()=>el('local-module-list').children.length===1&&!el('local-module-file').disabled); + assert(!el('local-module-list').querySelector('svg'),'Filename renders as text'); + assert(el('local-module-list').textContent.includes(file.manifest),'Visible manifest import statement'); + await status('Compiled'); + select(file.bytes);await wait(()=>el('local-module-status').textContent.includes('already available')); + equal(el('local-module-list').children.length,1,'Duplicates are idempotent'); + select(new Uint8Array([0]));await wait(()=>el('local-module-status').textContent.includes('Truncated')); + equal(el('local-module-list').children.length,1,'Invalid files preserve collection'); + select(file.bytes);el('cancel-local-module').click();await wait(()=>el('local-module-status').textContent.includes('cancelled')); + equal(el('local-module-list').children.length,1,'Cancelling validation preserves collection'); + const consumer=`!import ${file.manifest} as Mine\n!export answer\nanswer = Mine.plus 33`; + input('source-editor',consumer);el('compile').click();await status('Compiled'); + input('expression-editor','Mine.echo answer');change('output-type','number');el('run').click();await status('Finished'); + equal(el('result').textContent,'42','File selection makes module importable'); + // Stop an actually divergent export, then rebuild using page-owned local bytes. + input('source-editor','!export bad\nq x = x x\nbad = q q');el('compile').click();await status('Compiled'); + el('export-compiled-module').click();await status('Exporting module');await delay(150);el('stop').click();await status('Stopped'); + assert(el('export-compiled-module').disabled,'Stop invalidates exportable draft'); + input('source-editor',consumer);el('compile').click();await status('Compiled'); + change('runtime-backend',backend==='haskell-wasm'?'zig-wasm':'haskell-wasm'); + el('compile').click();await status('Compiled');input('expression-editor','answer');el('run').click();await status('Finished'); + equal(el('result').textContent,'42','Local bytes survive Stop and backend replacement'); + const frame=document.createElement('iframe');frame.src=new URL('index.html?noProbe=1',base).href;document.body.append(frame); + await wait(()=>frame.contentDocument?.getElementById('status')?.textContent==='Ready'); + equal(frame.contentDocument.getElementById('local-module-list').children.length,0,'A new page has no persisted local modules');frame.remove(); + [...el('local-module-list').querySelectorAll('button')].find(b=>b.textContent==='Remove').click(); + await status('Compilation failed');equal(el('local-module-list').children.length,0,'Removal clears module'); + assert(el('run').disabled&&el('export-compiled-module').disabled,'Removed dependency cannot use a stale compiled scope'); + return {userAgent:navigator.userAgent,source,manifest:exported.manifest,bytes:[...exported.bytes],checks:['local file validation; offline local-first imports; public portable export/reexport; shared DAGs; no private divergence; actual export/file import; duplicates/corruption; Stop/backend retention; page-only lifetime; removal invalidation']}; +} diff --git a/ext/demo-site/test/local-modules.test.mjs b/ext/demo-site/test/local-modules.test.mjs @@ -0,0 +1,61 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import {makeBundle,sizedBundle} from './bundle-fixture.mjs'; +import {decodeBundle,sha256} from '../dist/bundle.js'; +import {encodeModule,moduleSnapshot} from '../dist/module-bundle.js'; +import {validateLocalModule,localModuleInputs} from '../dist/local-modules.js'; +import {moduleIdentity} from '../dist/module-identity.js'; +import {moduleDependencies} from '../dist/module-stage.js'; + +test('local modules validate complete interfaces and distinct manifest/bundle identities',async()=>{ + const bytes=makeBundle([[],[0],[0,1]],[['left',2],['right',1]]); + const local=await validateLocalModule(bytes); + assert.equal(local.hash,await sha256(bytes));assert.equal(local.manifest,await moduleIdentity(decodeBundle(bytes))); + assert.notEqual(local.hash,local.manifest);assert.deepEqual(local.names,['left','right']); + bytes[0]=0;assert.equal(local.bytes[0],65,'owned immutable byte snapshot'); + await assert.rejects(()=>validateLocalModule(bytes),/magic/); + await assert.rejects(()=>validateLocalModule(makeBundle([[]],[['not a name',0]])),/interface/); + await assert.rejects(()=>validateLocalModule(makeBundle([[]],[['x',0]],{evaluation:'other'})),/semantics/); + await assert.rejects(()=>validateLocalModule(new Uint8Array(16777217)),/16 MiB/); +}); +test('local-first resolution is offline and never falls back after corrupt local input',async()=>{ + const entry=await validateLocalModule(makeBundle([[],[0]],[['value',1]])); + const stage={native:true,body:'',imports:[[entry.manifest,'L']],exports:[]}; + const fetch=globalThis.fetch;globalThis.fetch=()=>{throw Error('Unexpected network access');}; + try{ + const modules=await moduleDependencies(new URL('https://invalid.test/'),stage,[entry]); + assert.deepEqual([...modules.keys()],[entry.manifest]); + await assert.rejects(()=>moduleDependencies(new URL('https://invalid.test/'),stage,[{...entry,bytes:makeBundle([[]],[['value',0]])}]),/manifest mismatch/); + await assert.rejects(()=>moduleDependencies(new URL('https://invalid.test/'),stage,[{...entry,bytes:new Uint8Array([0])}]),/Truncated/); + }finally{globalThis.fetch=fetch;} +}); +test('local collection transfer bounds, duplicates and copies',async()=>{ + const entry=await validateLocalModule(makeBundle([[]])); + const inputs=localModuleInputs([entry]);entry.bytes[0]=0;assert.equal(inputs[0].bytes[0],65); + assert.throws(()=>localModuleInputs([entry,entry]),/Duplicate/); + assert.throws(()=>localModuleInputs(Array(33).fill(entry)),/count/); + assert.throws(()=>localModuleInputs([{manifest:'x',bytes:entry.bytes}]),/hash/); + assert.throws(()=>localModuleInputs([{...entry,bytes:[]}]),/byte/); + const large=sizedBundle(16777216); + assert.throws(()=>localModuleInputs(Array.from({length:5},(_,i)=>({manifest:String(i).repeat(64),bytes:large}))),/64 MiB/); +}); +test('portable module encoding canonicalizes duplicates without unfolding shared branches',async()=>{ + const nodes=[{kind:'leaf'},{kind:'leaf'},{kind:'stem',child:1},{kind:'stem',child:0}]; + for(let i=4;i<44;i++)nodes.push({kind:'fork',left:i-1,right:i-1}); + const bundle={nodes,exports:[{name:'deep',root:43},{name:'alias',root:43},{name:'small',root:2}],roots:[43],metadata:{}}; + const decoded=decodeBundle(encodeModule(bundle)); + assert.equal(decoded.nodes.length,42);assert.equal(decoded.exports[0].root,decoded.exports[1].root); + assert.equal(decoded.exports[2].root,1); + assert.ok(encodeModule(bundle).length<2000); + assert.deepEqual(encodeModule(decoded),encodeModule(bundle)); + assert.throws(()=>encodeModule({...bundle,exports:[{name:'duplicate',root:0},{name:'duplicate',root:1}]}),/duplicate/); +}); +test('module snapshots select public roots, drop synthetic list spine and refuse partial snapshots',()=>{ + const snapshot={root:5,aliases:[],truncated:false,nodes:[ + {id:0,kind:'leaf',children:[]},{id:1,kind:'stem',children:[0]}, + {id:3,kind:'fork',children:[1,0]},{id:5,kind:'fork',children:[1,3]}]}; + const bundle=decodeBundle(moduleSnapshot(['one','two'],snapshot)); + assert.equal(bundle.nodes.length,2);assert.deepEqual(bundle.exports.map(e=>e.root),[1,1]); + assert.throws(()=>moduleSnapshot(['one'],snapshot),/tail/); + assert.throws(()=>moduleSnapshot(['one','two'],{...snapshot,truncated:true}),/partial/); +}); diff --git a/ext/demo-site/test/module-goldens.json b/ext/demo-site/test/module-goldens.json @@ -0,0 +1,18 @@ +{ + "schema": 1, + "nativeCompilerSha256": "d70de875988dfa309f2c167992928866f88b08af351918b8c7b5d88c541c6e94", + "trees": [ + { + "source": "!import bd2c14d6db6b69308a5252a8e839705a55d30e815f012900b094315263e08d81 as B\n!export keep\nkeep x = B.pair x x", + "name": "keep", + "bytes": 17, + "ternaryAsciiSha256": "e08d3d2d682b2af2b15b0b043ee4198ca3d05843a21c9427c96e32a60863cd59" + }, + { + "source": "!import 7f87549d587fa8c3be88af0ea988db3adcc3b35f1ffb48973553491b075614db as N\n!export addTwo\naddTwo x = N.add x 2", + "name": "addTwo", + "bytes": 6034, + "ternaryAsciiSha256": "79d64391c7b4d730cb132a29ad7107ca1a56a7a2e2419abf8d5691503bd03496" + } + ] +} diff --git a/ext/demo-site/test/module-probe.mjs b/ext/demo-site/test/module-probe.mjs @@ -0,0 +1,143 @@ +// Production adapters + real page; expected values are independent arithmetic, +// native header contracts, and the CLI cases in native-modules.py. +const assert=(ok,message)=>{if(!ok)throw Error(message);}; +const equal=(actual,expected,label)=>assert(JSON.stringify(actual)===JSON.stringify(expected),label+': '+JSON.stringify(actual)); +async function rejects(fn,pattern){try{await fn();}catch(e){assert(pattern.test(e.message),'Wrong rejection: '+e.message);return;}throw Error('Expected '+pattern);} +const el=id=>document.getElementById(id),delay=ms=>new Promise(r=>setTimeout(r,ms)); +async function status(value){for(let i=0;i<4500;i++){if(el('status').textContent===value)return;await delay(20);}throw Error('Timed out '+value+': '+el('status').textContent+' '+el('compile-diagnostic').textContent);} +const input=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('input'));}; +const change=(id,value)=>{el(id).value=value;el(id).dispatchEvent(new Event('change'));}; +export async function run(control,backend='haskell-wasm'){ + const base=new URL('/nested/site/',location.href); + const {createRuntimeSession}=await import(new URL('dist/runtime-session.js',base)); + const {packageIndex,packageReleases}=await import(new URL('dist/packages.js',base)); + const releases=packageIndex(await(await fetch(new URL('packages.json',base))).json()); + const lib=name=>packageReleases(releases,'tricu-lib-'+name)[0]; + const math=lib('native-math'),foundation=lib('base'),io=lib('io'),modules=lib('source-module'); + const host={before:async()=>{},after:()=>{},write:()=>{},read:async()=>'',running:()=>{}}; + const fault=async data=>{await fetch(control+'/fault',{method:'POST',body:JSON.stringify(data)});}; + const source=`-- native header; position masking must preserve this line\n!import ${math.manifest} as N\n!export answer\nprivate = 99\nanswer = N.add 40 2`; + const s=await createRuntimeSession(backend,true); + const value=async expression=>(await s.runExpression(expression,'number','pure',host)).value; + try { + const catalogue=await(await fetch(new URL('catalogue.json',base))).json(); + const fixtures=await(await fetch('/zig-fixtures.json')).json(); + for(const demo of catalogue){ + assert(demo.environment==='empty','Every demo is editable without hidden helper injection'); + await s.compile(demo.source,demo.environment); + for(const c of fixtures.demos[demo.id].haskellCases){ + let terminal=''; + const result=await s.run(c.export,c.arguments.map(value=>({type:'tree',value})),'ternary',demo.mode, + {...host,read:async()=>c.input,write:text=>{terminal+=text;}}); + equal(result.value,c.result,'Recompiled demo golden '+demo.id); + equal(terminal,c.terminal,'Recompiled terminal '+demo.id); + } + } + equal(await s.compile(source),['answer'],'Only explicit public exports'); + equal(await value('answer'),'42','Qualified module application'); + equal(await value('N.add answer private'),'141','Imported and private local bindings survive expression runs'); + await s.compile(source,'practical'); + await rejects(()=>value('isNat? 1'),/unresolved name/); // native headers override legacy demo profiles + for(let i=0;i<10;i++)equal(await value('N.add answer 1'),'43','Repeated retained imported application'); + await rejects(()=>s.run('private',[],'number','pure',host),/Missing definition|missing export/); + equal(await s.compile(`!import ${foundation.manifest} *\n!export answer\nanswer = add 20 22`),['answer'],'Open full base has no implicit contract collisions'); + equal(await value('add answer 8'),'50','Open library helpers retained'); + await s.compile(`!import ${foundation.manifest} *\n!export checkedIdentity\ncheckedIdentity x =@nat? x`); + equal(await value('checkedIdentity 42'),'42','Native annotations resolve explicit contract imports'); + equal(await s.compile(`!import ${math.manifest} as A\n!import ${math.manifest} as B\n!export *\nanswer = A.add (B.add 10 11) 21`),['answer'],'Same manifest under two aliases'); + equal(await value('answer'),'42','Repeated reference'); + await s.compile(`!import ${modules.manifest} as M\n!export answer\nanswer = M.sourceModuleQualified "N" "add"`); + equal((await s.runExpression('answer','string','pure',host)).value,'N.add','Compiler helper library is ordinarily importable'); + const goldens=await(await fetch('/module-goldens.json')).json(); + for(const golden of goldens.trees){ + await s.compile(golden.source); + const tree=(await s.run(golden.name,[],'ternary','pure',host)).value; + equal(tree.length,golden.bytes,'Complete native function tree length'); + const hash=[...new Uint8Array(await crypto.subtle.digest('SHA-256',new TextEncoder().encode(tree)))].map(n=>n.toString(16).padStart(2,'0')).join(''); + equal(hash,golden.ternaryAsciiSha256,'Exact function tree agrees with independent native compiler'); + } + const names=await s.compile(`!export * from ${io.manifest}`); + assert(names.includes('io')&&names.includes('readFile')&&names.length>16,'Header-only full re-export'); + equal((await s.run('io',[{type:'number',value:'42'}],'tree','pure',host)).type,'tree','Re-export is executable, not source expansion'); + await rejects(()=>value('readFile'),/unresolved name/); // reexports do not introduce lexical imports + await s.compile(`!import ${io.manifest} as I\n!export main\nmain = I.io (I.readFile "no-browser-filesystem")`); + await rejects(()=>s.run('main',[],'string','io',host),/Unsupported.*20|unsupported.*20/i); + await s.compile(`!import ${math.manifest} as N\n!export answer\nloop x = loop x\nanswer = N.add 40 2`); + equal(await value('answer'),'42','Unused divergent function is never normalized'); + const failures=[ + [`!import ${math.manifest}\n!export answer\nanswer = 42`,/hash imports require an alias/], + [`!import ${math.manifest} as N\n!import ${math.manifest} as N\n!export answer\nanswer = 42`,/duplicate imported name/], + [`!import ${math.manifest} *\n!export add\nadd x y = x`,/Compiler diagnostic 46/], + [`!import ${math.manifest} as N\nanswer = 42`,/module requires an export/], + [`!export absent\nanswer = 42`,/undeclared local export/], + [`!export answer\n!export *\nanswer = 42`,/duplicate export/], + [`!export * from ${math.manifest}\n!export * from ${math.manifest}`,/duplicate export/], + [`!import prelude *\n!export answer\nanswer = 42`,/workspace/], + [`!source prelude\n!export answer\nanswer = 42`,/workspace/], + [`!import ${'0'.repeat(64)} as X\n!export answer\nanswer = 42`,/Unknown module manifest/], + [`!import ${math.manifest} as N\n!export answer\nanswer = missing`,/Compiler diagnostic 20 at 3:/], + ]; + for(const [text,pattern] of failures){ + await rejects(()=>s.compile(text),pattern); + await rejects(()=>value('answer'),/unresolved name/); + await s.compile(source);equal(await value('answer'),'42','Recover after failed module compilation'); + } + for(const field of ['moduleMissing','moduleCorrupt']){ + await fault({[field]:releases.find(r=>r.manifest===math.manifest).hash}); + await rejects(()=>s.compile(source),/HTTP 404|SHA-256 mismatch/); + await rejects(()=>value('answer'),/unresolved name/); + await fault({[field]:null}); + await s.compile(source);equal(await value('answer'),'42','Fetch retry'); + } + await fault({moduleManifest:math.manifest}); + await rejects(()=>s.compile(source),/Module manifest mismatch/); + await fault({moduleManifest:null}); + await s.compile(source); + const memory=[]; + for(let i=0;i<12;i++){ + await s.compile(source);equal(await value('N.add answer 1'),'43','Repeated module replacement'); + if(s.diagnostics){s.collect();memory.push(s.diagnostics());} + } + if(memory.length){ + equal(memory.at(-1).owned,memory[0].owned,'No retained import handle leak'); + assert(Math.max(...memory.slice(6).map(x=>x.linearMemoryBytes))<=Math.max(...memory.slice(0,6).map(x=>x.linearMemoryBytes))+65536,'Module memory plateaus'); + } + await s.compile(`!import ${math.manifest} as N\n!export answer\nbrowserExpression0 = 9\nanswer = 42`); + equal(await value('N.add answer browserExpression0'),'51','Temporary expression names avoid private locals'); + await s.compile('answer = 7');equal(await value('answer'),'7','Legacy scratch remains supported'); + await rejects(()=>value('N.add 1 2'),/unresolved name/); + }finally{s.dispose();await fault({moduleMissing:null,moduleCorrupt:null,moduleManifest:null});} + // Exercise the actual editable page, including Worker termination and rebuilding. + await status('Ready');change('runtime-backend',backend);await status('Ready'); + document.querySelector('[data-compiler-example=module]').click();await status('Compiled'); + assert(el('source-editor').value.includes(math.manifest),'Module example uses an indexed manifest, not a bundle digest'); + input('expression-editor','answer');change('output-type','number');el('run').click();await status('Finished'); + equal(el('result').textContent,'42','Module scratch example'); + input('source-editor',source);el('compile').click();await status('Compiled'); + equal([...el('export').options].map(x=>x.value),['answer'],'Page public selector'); + input('expression-editor','N.add answer private');change('output-type','number');el('run').click();await status('Finished'); + equal(el('result').textContent,'141','Actual page imported expression'); + input('source-editor',`!import ${math.manifest} as N\n!export answer\nloop x = loop x\nanswer = N.add 40 2`); + el('compile').click();await status('Compiled'); + input('expression-editor','loop t');el('run').click();await status('Running');await delay(100);el('stop').click();await status('Stopped'); + assert(el('run').disabled,'Stop discards imported heap'); + el('compile').click();await status('Compiled');input('expression-editor','N.add answer 1');el('run').click();await status('Finished'); + equal(el('result').textContent,'43','Stop/recompile reconstructs verified imports'); + // Edit the actual parser/lexer examples, not a scratch copy; verify changed + // behavior, then restore the authenticated original and its behavior. + for(const [id,before,after,expression,field,want,original] of [ + ['parser','N.inRange c 97 122','N.inRange c 65 90','parseNames "RED,GREEN"','status','ok','error'], + ['lexer','N.inRange character 97 122','N.inRange character 65 90','scanWord "HELLO,world"','matched','HELLO',''], + ]){ + change('program-picker','demo:'+id);await status('Ready'); + assert(!el('source-editor').hidden&&!el('source-editor').readOnly,'Editable '+id); + const source=el('source-editor').value;assert(source.includes(before),'Known predicate'); + input('source-editor',source.replace(before,after));el('compile').click();await status('Compiled'); + input('expression-editor',expression);change('output-type','record');el('run').click();await status('Finished'); + equal(JSON.parse(el('result').textContent)[field],want,'Edited '+id+' result'); + el('restore-source').click();await status('Ready');equal(el('source-editor').value,source,'Restore '+id); + input('expression-editor',expression);change('output-type','record');el('run').click();await status('Finished'); + equal(JSON.parse(el('result').textContent)[field],original,'Restored '+id+' behavior'); + } + return {userAgent:navigator.userAgent,checks:['all ten editable demos match native goldens; parser/lexer edit and restore; native headers; qualified/open imports; full reexports; retained private/import scope; collision/diagnostic controls; transport and manifest faults; no capabilities; repeated replacement/GC; actual page Stop/recompile']}; +} diff --git a/ext/demo-site/test/modules.test.mjs b/ext/demo-site/test/modules.test.mjs @@ -0,0 +1,104 @@ +import test from 'node:test'; +import assert from 'node:assert/strict'; +import {readFile, readdir} from 'node:fs/promises'; +import {decodeBundle, sha256} from '../dist/bundle.js'; +import {indexedObject, moduleIdentity, moduleHash} from '../dist/module-identity.js'; +import {fetchModule} from '../dist/module-resolver.js'; +import {packageIndex, packageReleases} from '../dist/packages.js'; +const site = new URL('../', import.meta.url), root = new URL('../../', site); +const releases = packageIndex(JSON.parse(await readFile(new URL('packages.json', site)))); +const bytes = r => readFile(new URL(`bundles/${r.hash}.arboricx`, site)); +const libraries = [...new Set(releases.filter(r => r.name.startsWith('tricu-lib-')).map(r => r.name))] + .map(name => packageReleases(releases, name)[0]); + +test('every library source has a complete-interface package; no module allowlist', async () => { + const paths = []; + async function walk(directory) { + for (const entry of await readdir(new URL(directory, root), {withFileTypes:true})) { + const path = directory + entry.name; + if (entry.isDirectory()) await walk(path + '/'); + else if (entry.name.endsWith('.tri')) paths.push(path); + } + } + await walk('lib/'); + assert.deepEqual(libraries.map(r => r.title).sort(), paths.sort()); + for (const cohort of ['compiler-library', 'support-library']) { + const fixture = decodeBundle(await readFile(new URL(`test/fixtures/${cohort}.arboricx`, root))); + const metadata = await readFile(new URL(`test/fixtures/${cohort}.v1`, root), 'utf8'); + for (const row of metadata.split('\n').filter(s => s.startsWith('module\t'))) { + const [, , alias, path] = row.split('\t'); + if (!path.startsWith('lib/')) continue; + const release = libraries.find(r => r.title === path); + assert.ok(release, path); + const bundle = decodeBundle(await bytes(release)); + assert.deepEqual(bundle.exports.map(e => e.name), fixture.exports.filter(e => e.name.startsWith(alias + '.')).map(e => e.name.slice(alias.length + 1)), path); + } + } +}); + +test('browser manifest identities match every independently native-published library interface', async () => { + assert.ok(libraries.length > 0); + for (const release of libraries) { + const data = await bytes(release); + assert.equal(await sha256(data), release.hash, release.name); + assert.equal(await moduleIdentity(decodeBundle(data)), release.manifest, release.name); + } +}); + +test('indexed extraction is name-neutral, ignores unrelated roots/metadata, preserves physical sharing', async () => { + const b = decodeBundle(await readFile(new URL('test/fixtures/id.arboricx', root))); + const expected = await sha256(indexedObject(b, b.exports[0].root)); + b.metadata = {description:'not executable identity'}; + b.exports[0].name = 'renamed'; + b.nodes.push({kind:'fork',left:0,right:0}); + assert.equal(await sha256(indexedObject(b, b.exports[0].root)), expected); + const shared = {nodes:[{kind:'leaf'}],roots:[31],exports:[{name:'tree',root:31,kind:'term',abi:'arboricx.abi.tree.v1'}],metadata:{}}; + for(let i=1;i<=31;i++) shared.nodes.push({kind:'fork',left:i-1,right:i-1}); + const object = indexedObject(shared,31); + assert.ok(object.length < 2048); + assert.equal(decodeBundle(object).nodes.length,32); + assert.equal((await moduleIdentity(shared)).length,64); + await assert.rejects(moduleIdentity({...shared,exports:[]}), /nonempty native/); + await assert.rejects(moduleIdentity({...shared,exports:[{...shared.exports[0],name:'bad name'}]}), /native module/); + assert.throws(()=>moduleHash('../path'), /hash/); +}); + +test('manifest transport rejects unknown refs, wrong manifest, corrupt bytes and HTTP failure', async () => { + const release = libraries.find(r => r.title === 'lib/packages/io.tri'); + const data = await bytes(release), calls = [], original = globalThis.fetch; + let response = () => new Response(data); + globalThis.fetch = async (url, options) => { calls.push({url:String(url),options}); return response(); }; + const base = new URL('https://example.invalid/nested/site/'); + try { + const loaded = await fetchModule(base, release.manifest, releases); + assert.equal(loaded.exports.length,6); + assert.equal(calls[0].url, `https://example.invalid/_arboricx/bundle/hash/${release.hash}`); + assert.deepEqual(calls[0].options, {redirect:'error',credentials:'omit'}); + const count = calls.length; + await assert.rejects(fetchModule(base, '0'.repeat(64), releases), /Unknown module manifest/); + await assert.rejects(fetchModule(base, release.hash, releases), /Unknown module manifest/); + assert.equal(calls.length,count); + await assert.rejects(fetchModule(base, '0'.repeat(64), [{...release,manifest:'0'.repeat(64)}]), /Module manifest mismatch/); + response = () => new Response(new Uint8Array([1,2,3])); + await assert.rejects(fetchModule(base, release.manifest, releases), /SHA-256 mismatch/); + response = () => new Response('missing',{status:404}); + await assert.rejects(fetchModule(base, release.manifest, releases), /HTTP 404/); + response = () => new Response(data); + assert.equal((await fetchModule(base, release.manifest, releases)).exports.length,6); + } finally { globalThis.fetch = original; } +}); + +test('native-parsed export projection retains opaque trees without evaluating them', async () => { + const {selectModuleExports} = await import('../dist/module-stage.js'); + const value = new Proxy({}, {get(){throw Error('Executable tree must remain opaque');}}); + const locals = new Map([['private', value], ['answer', value]]); + const dependencies = new Map([['pin', new Map([['id', value]])]]); + const stage = exports => ({body:'',imports:[],exports,native:true}); + assert.deepEqual([...selectModuleExports(stage([['answer','']]),locals,dependencies).keys()],['answer']); + assert.deepEqual([...selectModuleExports(stage([['*',''],['from','pin']]),locals,dependencies).keys()],['private','answer','id']); + for(const [exports,pattern] of [[[],/requires an export/],[[['absent','']],/undeclared local/],[[['answer',''],['*','']],/duplicate export/],[[['from','missing']],/Missing re-export/]]){ + assert.throws(()=>selectModuleExports(stage(exports),locals,dependencies),pattern); + } + const huge = new Map(Array.from({length:4097},(_,i)=>['n'+i,value])); + assert.throws(()=>selectModuleExports(stage([['*','']]),huge,dependencies),/export limit/); +}); diff --git a/ext/demo-site/test/native-modules.py b/ext/demo-site/test/native-modules.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Independent native CLI expectations for browser module semantics. + +Uses the shipped stable compiler and the site's exact complete-interface bundles +for independent native checks. Run with a Nix-built tricu. Temporary indexed +stores are removed on exit. +""" +import argparse +import hashlib +import json +from pathlib import Path +import re +import subprocess +import sys +import tempfile + +ROOT = Path(__file__).resolve().parents[3] +SITE = ROOT / 'ext/demo-site' +sys.path.insert(0, str(ROOT / 'test')) +from bundle_dag import read +from shipped_compiler import verify + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('tricu', type=Path) + parser.add_argument('--capture', type=Path, help='Explicitly capture independent complete-tree digests') + args = parser.parse_args() + host = args.tricu.resolve() + metadata = verify() + releases = json.loads((SITE / 'packages.json').read_text())['releases'] + def library(name): + # An immutable known release, not an expected value generated by a browser. + return next(r for r in releases if r['name'] == 'tricu-lib-' + name and r['version'] == '0.1.0') + math, base, io, modules = [library(n) for n in ['native-math', 'base', 'io', 'source-module']] + with tempfile.TemporaryDirectory(prefix='tricu-browser-native-modules-') as temporary: + work = Path(temporary) + (work / 'tricu.workspace').write_text('tricu.workspace.v1\n') + def run(*words, success=True): + result = subprocess.run([str(host), *map(str, words), '+RTS', '-N1', '-M2048m', '-RTS'], + cwd=work, capture_output=True, timeout=120) + output = (result.stdout + result.stderr).decode() + if (result.returncode == 0) != success: + raise AssertionError(output) + return output.strip() + def imported(file, store): + text = run('arboricx', 'import', '--indexed', '--store', store, '--file', file) + return re.search(r'Created module alias .* -> ([0-9a-f]{64})', text)[1] + compiler = imported(ROOT / metadata['bundle'], work / 'tools') + for release in [math, base, io, modules]: + assert imported(SITE / 'bundles' / (release['hash'] + '.arboricx'), work / 'store') == release['manifest'] + def compile_source(source, success=True): + (work / 'main.tri').write_text(source) + output = work / 'out.arboricx' + output.unlink(missing_ok=True) + diagnostic = run('arboricx', 'compile', '--file', work / 'main.tri', '--store', work / 'store', + '--toolchain', compiler, '--tool-store', work / 'tools', '--output', output, + '--compile-timeout', '110', success=success) + if not success: + assert not output.exists() + return diagnostic + return imported(output, work / 'consumer'), list(read(output)[3]) + cases = [ + (f'!import {math["manifest"]} as N\n!export answer\nprivate = 99\nanswer = N.add 40 2', 'number', '42'), + (f'!import {math["manifest"]} as N\n!export answer\nprivate = 99\nanswer = N.add (N.add 40 2) private', 'number', '141'), + (f'!import {base["manifest"]} *\n!export answer\nanswer = add 20 22', 'number', '42'), + (f'!import {base["manifest"]} *\n!export answer\ncheckedIdentity x =@nat? x\nanswer = checkedIdentity 42', 'number', '42'), + (f'!import {math["manifest"]} as A\n!import {math["manifest"]} as B\n!export *\nanswer = A.add (B.add 10 11) 21', 'number', '42'), + (f'!import {modules["manifest"]} as M\n!export answer\nanswer = M.sourceModuleQualified "N" "add"', 'string', 'N.add'), + (f'!import {math["manifest"]} as N\n!export answer\nloop x = loop x\nanswer = N.add 40 2', 'number', '42'), + ] + for source, format, expected in cases: + manifest, names = compile_source(source) + assert names == ['answer'], names + actual = run('arboricx', 'run', '--module', manifest, '--store', work / 'consumer', + '--name', 'answer', '--format', format) + assert actual == (json.dumps(expected) if format == 'string' else expected), (format, actual, expected) + manifest, names = compile_source('!export * from ' + io['manifest']) + assert manifest == io['manifest'] + assert names == list(read(SITE / 'bundles' / (io['hash'] + '.arboricx'))[3]) + tree_cases = [ + ('keep', f'!import {base["manifest"]} as B\n!export keep\nkeep x = B.pair x x'), + ('addTwo', f'!import {math["manifest"]} as N\n!export addTwo\naddTwo x = N.add x 2'), + ] + trees = [] + for name, source in tree_cases: + manifest, names = compile_source(source) + assert names == [name] + tree = run('arboricx', 'run', '--module', manifest, '--store', work / 'consumer', + '--name', name, '--format', 'ternary') + assert tree and set(tree) <= set('012') + trees.append(dict(source=source, name=name, bytes=len(tree), + ternaryAsciiSha256=hashlib.sha256(tree.encode('ascii')).hexdigest())) + evidence = dict(schema=1, nativeCompilerSha256=metadata['sha256'], trees=trees) + if args.capture: + args.capture.write_text(json.dumps(evidence, indent=2) + '\n') + else: + assert evidence == json.loads((SITE / 'test/module-goldens.json').read_text()) + failures = [ + (f'!import {math["manifest"]}\n!export answer\nanswer = 42', 'hash imports require an alias'), + (f'!import {math["manifest"]} as N\n!import {math["manifest"]} as N\n!export answer\nanswer = 42', 'duplicate imported name'), + (f'!import {math["manifest"]} as N\nanswer = 42', 'module requires an export'), + ('!export absent\nanswer = 42', 'undeclared local export'), + ('!export answer\n!export *\nanswer = 42', 'duplicate export'), + (f'!export * from {io["manifest"]}\n!export * from {io["manifest"]}', 'duplicate'), + ] + for source, message in failures: + diagnostic = compile_source(source, False) + assert message in diagnostic, diagnostic + for source in [ + f'!import {math["manifest"]} *\n!export add\nadd x y = x', + f'!export * from {io["manifest"]}\n!export answer\nanswer = readFile', + ]: + compile_source(source, False) + print('Native module oracle passed: values, full reexports, import/export collisions, lexical scope and failed publication') + + +if __name__ == '__main__': + main() diff --git a/ext/demo-site/test/packages.test.mjs b/ext/demo-site/test/packages.test.mjs @@ -80,10 +80,10 @@ test('showcase packages retain browser-bounded complete library roots and native } }); -test('native parser demo source and goldens are authenticated without claiming a browser compile environment',async()=>{ +test('native parser demo source and goldens are authenticated with an editable native module environment',async()=>{ const catalogue=JSON.parse(await read('catalogue.json')),demo=catalogue.find(e=>e.id==='parser'); const goldens=JSON.parse(await read('parser-demo.json')); - assert.equal(demo.preparation,'native');assert.equal(demo.environment,undefined); + assert.equal(demo.preparation,'native');assert.equal(demo.environment,'empty'); assert.equal(createHash('sha256').update(demo.source).digest('hex'),demo.sourceSha256); assert.equal(demo.source,await read('demos/parser.tri').then(b=>b.toString())); assert.equal(goldens.hash,demo.hash);assert.equal(goldens.sourceSha256,demo.sourceSha256); @@ -128,7 +128,7 @@ test('new practical libraries expose complete interfaces and lexer reference sou if(name==='tricu-list-traversal'||name==='tricu-patterns')assert.deepEqual(names.sort(),required.sort()); } const demo=JSON.parse(await read('catalogue.json')).find(e=>e.id==='lexer'),goldens=JSON.parse(await read('lexer-demo.json')); - assert.equal(demo.preparation,'native');assert.equal(demo.environment,undefined); + assert.equal(demo.preparation,'native');assert.equal(demo.environment,'empty'); assert.equal(demo.source,await read('demos/lexer.tri').then(b=>b.toString())); assert.equal(createHash('sha256').update(demo.source).digest('hex'),demo.sourceSha256); assert.equal(goldens.hash,demo.hash);assert.equal(goldens.sourceSha256,demo.sourceSha256); @@ -149,3 +149,19 @@ test('release choices are newest-first, numeric, independent of publication orde const labels=['build2','build10','0.1.0'].map(version=>({...releases[0],version})); assert.deepEqual(packageReleases(labels,'demo').map(r=>r.version),['0.1.0','build10','build2']); }); + +test('every catalogue demo is editable, source-authenticated and explicitly imports indexed manifests',async()=>{ + const catalogue=JSON.parse(await read('catalogue.json')),index=packageIndex(JSON.parse(await read('packages.json'))); + assert.equal(catalogue.length,10); + for(const demo of catalogue){ + assert.equal(demo.environment,'empty',demo.id); + assert.equal(demo.source,(await read('demos/'+demo.id+'.tri')).toString()); + assert.equal(createHash('sha256').update(demo.source).digest('hex'),demo.sourceSha256); + assert.match(demo.source,/^!export /m); + for(const line of demo.source.split('\n').filter(s=>s.startsWith('!import '))){ + const match=line.match(/^!import ([0-9a-f]{64}) (?:\*|as [A-Za-z_][A-Za-z0-9_]*)$/);assert.ok(match,line); + assert.ok(index.some(r=>r.manifest===match[1]),line); + } + assert.doesNotMatch(demo.source,/Tree graph|copy it into Compiler|source is read-only|input box uses JSON/); + } +}); diff --git a/ext/demo-site/test/release.py b/ext/demo-site/test/release.py @@ -40,9 +40,17 @@ def main(): for script in ['wasm-worker.js']: source = (args.site / 'dist' / script).read_text() assert './published-bundle.js' in source and 'bundles/' not in source - for script in ['published-bundle.js', 'haskell-session.js']: - source = (args.site / 'dist' / script).read_text() + # Resolution moved inside the runtime Worker so headers decide whether a + # legacy profile is needed. Check the actual download owners, not the old + # Haskell session forwarding adapter, while retaining the no-static-fallback + # control for every production route. + for script in ['dist/published-bundle.js', 'dist/module-resolver.js', + 'runtime/haskell/worker.mjs', 'runtime/zig/site-session.mjs']: + source = (args.site / script).read_text() assert '/_arboricx/bundle/hash/' in source and 'bundles/' not in source + assert 'bundles/' not in (args.site / 'dist/haskell-session.js').read_text() + assert (args.site / 'dist/local-module-worker.js').is_file() + assert (args.site / 'dist/local-modules-ui.js').is_file() for backend, binary, scripts in [ ('haskell', 'reactor.wasm', ['client.mjs', 'worker.mjs', 'bridge.mjs', 'pins.mjs']), ('zig', 'arboricx.wasm', ['runtime.mjs', 'site-session.mjs']), @@ -50,8 +58,24 @@ def main(): runtime = args.site / 'runtime' / backend assert (runtime / binary).read_bytes()[:8] == b'\x00asm\x01\x00\x00\x00' assert all((runtime / name).is_file() for name in scripts) - for name in ['shim/index.js', 'data/compiler.dag', 'data/environment.tsv', 'site/bundle.js']: + for name in ['shim/index.js', 'data/compiler.dag', 'data/environment.tsv', + 'data/compiler-exports.tsv', 'site/bundle.js', 'site/module-stage.js', + 'site/module-resolver.js', 'site/module-identity.js', 'site/local-modules.js', + 'site/module-bundle.js']: assert (args.site / 'runtime/haskell' / name).is_file() + runtime = args.site / 'runtime/haskell' + pins = json.loads((runtime / 'pins.mjs').read_text().split('export default ', 1)[1].split(';', 1)[0]) + for name in ['compiler.dag', 'environment.tsv', 'compiler-exports.tsv']: + assert hashlib.sha256((runtime / 'data' / name).read_bytes()).hexdigest() == pins[name] + dag = (runtime / 'data/compiler.dag').read_bytes() + count_nodes = int.from_bytes(dag[:4], 'little') + table = [row.split('\t') for row in (runtime / 'data/compiler-exports.tsv').read_text().splitlines()] + assert len({name for name, _ in table}) == len(table) + assert all(index.isdecimal() and 0 <= int(index) < count_nodes for _, index in table) + roots = dict(table) + assert int(roots[compiler['export']]) == int.from_bytes(dag[4:8], 'little') + assert all('source_module.' + name in roots for name in + ['sourceModuleHeaderStage', 'sourceModuleUseShape', 'sourceModuleExportShape', 'sourceModuleQualified']) spec = importlib.util.spec_from_file_location('seed', args.seeder) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) diff --git a/ext/demo-site/test/showcase-preparation.test.mjs b/ext/demo-site/test/showcase-preparation.test.mjs @@ -76,7 +76,7 @@ print('accepted') assert.equal(output.trim(),'accepted'); }); -test('historical browser preparation preserves native demos without assigning an editable environment',async()=>{ +test('core preparation preserves separately accepted native demo editability',async()=>{ const prepare=await readFile(new URL('../prepare.py',import.meta.url),'utf8'); const index=await readFile(new URL('../prepare-index.py',import.meta.url),'utf8'); assert.match(prepare,/catalogue\.extend\(entry for entry in previous if entry\.get\('preparation'\) == 'native'/); diff --git a/ext/demo-site/test/site.test.mjs b/ext/demo-site/test/site.test.mjs @@ -21,7 +21,7 @@ test('single flowing editor starts before ecosystem, without tabs or graph JSON test('editor preserves authoring, IO, package and immutable download controls',async()=>{ const html=await read('index.html'); for(const id of ['source-editor','expression-editor','compile','stop','restore-source','output-type','mode','step-mode','input-form','line-input','next','arguments','raw-arguments','use-guided-inputs','download-bundle','package-version','program-hash','share'])assert.ok(html.includes(`id="${id}"`),id); - assert.match(html,/Edits compile after a pause/);assert.match(html,/Stored definitions are read without evaluation/); + assert.match(html,/Edits compile after a pause/);assert.match(html,/Stored definitions use the original bundle records/); assert.doesNotMatch(html,/id="edit-source"|compile-consent|slow-compilation|uncapped|execution-limits/); const app=await read('src/app.ts');assert.match(app,/sourceEditor.classList.toggle\('modified', sourceModified\)/); assert.match(app,/sourceEditor.value !== compiledSource/); diff --git a/ext/demo-site/test/zig-session-probe.mjs b/ext/demo-site/test/zig-session-probe.mjs @@ -73,14 +73,16 @@ export async function run() { } const intro=fixtures.demos.intro;await c.compile(intro.source,'empty'); await rejects(()=>c.compile('name = unavailableName','empty'),/Compiler diagnostic/); - equal((await c.run('answer',[],'number','pure',host())).value,'42','Compile error preserves definitions'); + // Retired stale-definition retention: a failed replacement cannot expose the + // previous program or its imported scope. Runtime/IO errors still retain it. + await rejects(()=>c.run('answer',[],'number','pure',host()),/Missing definition/); const greet=fixtures.demos.greet;await c.compile(greet.source,'empty'); await rejects(()=>c.run(greet.haskellCases[0].export,[],'string','io',{...host('x'),before:async()=>{throw Error('host failed');}}),/host failed/); const first=greet.haskellCases[0];equal(await c.inspect(first.export,[],greet.mode,host(first.input)),first.result,'Host-error cleanup preserves definitions'); await c.compile('q x = x x\nlazy = t (q q) t\naborted = t \"tricuIO\" (t 1 (t 2 (q q)))','empty'); const partial=await c.preview('lazy',1);assert(partial.nodes.length===1&&partial.truncated,'Preview forced excluded divergent child'); await rejects(()=>c.run('aborted',[],'tree','io',host()),/aborted/); - report.checks.push('eight complete source demos/environment profiles; compile/host-error retention; nonforcing divergent preview/abort'); + report.checks.push('ten complete native source demos; compile-error invalidation/host-error retention; nonforcing divergent preview/abort'); }finally{c.dispose();} return report; } diff --git a/ext/haskell-wasm/BrowserModules.hs b/ext/haskell-wasm/BrowserModules.hs @@ -0,0 +1,88 @@ +-- The source grammar/shape checks and body compiler remain portable trees. +-- This adapter hydrates verified closed exports and projects the native-parsed +-- public interface without publishing/hashing (and thereby forcing) new trees. +module BrowserModules where +import Runtime.Tree +import Runtime.Value +import qualified CompilerProbe as C +import Control.Monad (unless, foldM) +import Data.List (nub) +import qualified BrowserRuntime as R + +type Bindings = [(String,T)] +data Stage = Stage { body :: String, uses :: [(String,String)], exports :: [(String,String)] } + +helper :: Bindings -> String -> [T] -> T +helper library name args = case lookup ("source_module." ++ name) library of + Nothing -> error "Missing native module compiler helper" + Just f -> foldl apply f args + +result :: Bool -> T -> IO T +result diagnostic tree = case C.pair tree of + (Stem Leaf,payload) -> pure (fst (C.pair payload)) + (Leaf,payload) -> fail (if diagnostic then C.diagnostic payload else C.text (fst (C.pair payload))) + _ -> fail "Invalid native module result" + +boundedList :: Int -> T -> IO [T] +boundedList limit tree = do + values <- either fail pure (toList tree) + unless (length (take (limit+1) values) <= limit) (fail "Module list limit exceeded") + pure values + +stage :: Bindings -> String -> IO Stage +stage library source = do + unless (not (null source) && length source <= 16384) (fail "source scalar limit exceeded") + parsed <- result True (helper library "sourceModuleHeaderStage" [ofString source]) + let (edges,rest) = C.pair parsed + (imports,tail1) = C.pair rest + (selected,masked) = C.pair tail1 + dependencies <- boundedList 16384 edges + unless (null dependencies) (fail "Browser modules require manifest hashes; workspace and build-only sources are unavailable") + let shapes name rows = do + values <- boundedList 16384 rows + mapM (\row -> do + spec <- result False (helper library name [row]) + let (a,b) = C.pair spec + let left = C.text a; right = C.text b + unless (length left <= 128 && length right <= 128) (fail "Module header name limit exceeded") + pure (left,right)) values + us <- shapes "sourceModuleUseShape" imports + es <- shapes "sourceModuleExportShape" selected + pure (Stage (C.text masked) us es) + +native :: Stage -> Bool +native s = not (null (uses s) && null (exports s)) + +stageJSON :: Stage -> R.J +stageJSON s = R.O [("body",R.S (body s)),("imports",pairs (uses s)),("exports",pairs (exports s)),("native",R.B (native s))] + where pairs rows = R.A [R.A [R.S a,R.S b] | (a,b) <- rows] + +compile :: Bindings -> T -> Stage -> [(String,Bindings)] -> IO (Bindings,Bindings) +compile library compiler s modules = do + let dependency ref = maybe (fail "Missing module dependency") pure (lookup ref modules) + extend env (ref,alias) = do + entries <- dependency ref + foldM (\bindings (name,tree) -> do + let qualified = C.text (helper library "sourceModuleQualified" [ofString alias,ofString name]) + unless (length qualified <= 4096 && not (qualified `elem` map fst bindings)) (fail "duplicate imported name") + unless (length bindings < 4096) (fail "Module binding limit exceeded") + pure (bindings ++ [(qualified,tree)])) env entries + imported <- foldM extend [] (uses s) + let env = ofList [Fork (ofString name) tree | (name,tree) <- imported] + locals <- either fail pure (C.definitions (C.compile compiler env (ofString (body s)))) + let names = map fst (take 17 locals) + unless (length names <= 16 && all (\n -> not (null n) && length n <= 128) names && length (nub names) == length names) + (fail "invalid compiler definition names") + let add selected (name,tree) = do + unless (not (name `elem` map fst selected)) (fail "duplicate export") + unless (length selected < 4096) (fail "Module export limit exceeded") + pure (selected ++ [(name,tree)]) + select selected (name,ref) + | name == "from" = dependency ref >>= foldM add selected + | name == "*" = foldM add selected locals + | otherwise = case lookup name locals of + Nothing -> fail "undeclared local export" + Just tree -> add selected (name,tree) + public <- foldM select [] (exports s) + unless (not (null public)) (fail "module requires an export") + pure (public,locals ++ imported) diff --git a/ext/haskell-wasm/CompilerProbe.hs b/ext/haskell-wasm/CompilerProbe.hs @@ -17,6 +17,7 @@ import System.Environment (getArgs) import System.Exit (die) import System.Mem (performGC) import Text.Printf (printf) +import Text.Read (readMaybe) now :: IO Double now = (/1e9) . fromIntegral <$> getMonotonicTimeNSec @@ -29,6 +30,11 @@ word b at = fromIntegral (foldr (.|.) 0 [fromIntegral (BS.index b (at+j)) `shift -- Bounds and backward references are checked before constructing the lazy array. load :: FilePath -> IO (T,T) load dir = do + (compiler, env, _) <- loadLibrary dir + pure (compiler, env) + +loadLibrary :: FilePath -> IO (T,T,[(String,T)]) +loadLibrary dir = do b <- BS.readFile (dir++"/compiler.dag") unless (BS.length b >= 8) (die "truncated DAG") let n=word b 0; root=word b 4 @@ -52,7 +58,11 @@ load dir = do _ -> die "invalid environment binding") bindings let environment=ofList env _<-evaluate (forceSpine environment) - pure (trees!root, environment) + exported <- lines <$> utf8 (dir++"/compiler-exports.tsv") + library <- mapM (\line -> case words line of + [name,idx] | Just i <- readMaybe idx, i>=0 && i<n -> pure (name,trees!i) + _ -> die "invalid compiler export") exported + pure (trees!root, environment, library) force :: T -> () force Leaf=() diff --git a/ext/haskell-wasm/README.md b/ext/haskell-wasm/README.md @@ -126,9 +126,9 @@ bulk Haskell response encoding; round-trip timings also include Worker messaging and main-thread UTF-8 decoding. Do not compare these measurements directly with fresh-process Node timings without accounting for the different boundaries. -Additional controls cover both prepared-input hashes, valid Unicode source +Additional controls cover prepared-input hashes, valid Unicode source against an independent scalar-tree golden, lone-surrogate/oversized source, -malformed ternary input, preservation of prior definitions after a failed compile, +malformed ternary input, invalidation of prior definitions after a failed compile, single-flight request rejection, 30 compile/run/reset cycles, inaccessible exports after reset, a main-thread heartbeat during divergent reduction, deadline-triggered termination, rejection of further requests to the disposed Worker, and successful @@ -138,7 +138,8 @@ execution in a replacement Worker. against 117 existing Haskell result/terminal goldens, including four Conversation IO cases, then compiles all eight sources using the empty/practical environments. It checks all seven output codecs, invalid bytes/scalars/records, authentication -and profile rejection without losing prior exports, a 40-level exponentially +and profile rejection (failed loads preserve exports; failed compile replacements +invalidate them), a 40-level exponentially shared tree, bounded preview, immutable and runtime DAG export, and refusal to export truncated snapshots or oversized expanded trees. IO controls cover sentinel version, unsupported actions, action/output limits, stale replies, GC while @@ -157,20 +158,24 @@ loader and exercises neither asynchronous JSFFI nor Haskell parallelism. Each Worker owns one runtime, an optional retained compiler/environment and at most one current definition set. Source is UTF-8 copied into Haskell-owned bytes before the JS allocation is freed. A successful compilation atomically replaces the -definitions after its names response is materialized; failure preserves the -preceding set. Program trees stay lazy until inspected or applied. `dump` and +definitions after its names response is materialized. Starting a replacement +clears the preceding public interface and expression scope, including on failure. +Native modules retain a separate local/import expression scope. Imports supply +lexical bindings; reexports select dependency exports for the public interface. Header parsing and +name qualification invoke authenticated `source_module` trees, with bindings +hydrated from bundles verified against both transport and manifest pins. The +`compiler-exports.tsv` root table is authenticated with the prepared compiler kit. Program trees stay lazy until inspected or applied. `dump` and `observe` produce a bounded bulk UTF-8 response. Haskell copies that response into a JS-requested WASM buffer and clears its retained reference. JS clones the buffer, frees it, and transfers the resulting ArrayBuffer to the parent. -No per-node handles, native addresses, or Haskell heap pointers cross to the UI. +The UI receives serialized values and runtime statistics. Legacy `observe`/`dump` ternary output expands sharing and is retained for benchmark comparisons only. `preview`/`snapshot` use local IDs, stable-name -identity with collision checks, and explicit aliases; no label is a persistent -runtime handle. Preview registers child references without forcing excluded -children. A complete snapshot is converted to the site's immutable DAG export +identity with collision checks, and explicit aliases. Labels are scoped to each +snapshot. Preview registers child references and observes nodes within its budget. A complete snapshot is converted to the site's immutable DAG export input, rejecting partial graphs and cycles. Stored package export uses the -original validated bundle records and never evaluates the stored program. -The embedding's framed binary wire is private, not a public interchange format. +original validated bundle records. The framed binary wire serves the private +embedding protocol. The JS wrapper refreshes linear-memory views after calls that might grow memory. `reset` discards current definitions and collects while retaining the compiler; @@ -226,8 +231,8 @@ protocol: | `init` | Default loads the build-pinned compiler kit; `compiler:false` starts a package-only session without downloading the kit. Ready identifies `compilerHash` (or null). | | `load` | `bytes: ArrayBuffer`, lowercase whole-bundle `hash`; returns export names, atomically replaces definitions. | | `compiler-init` | Lazily authenticate/load the prepared compiler kit into an existing package session; returns `compilerHash` without replacing definitions. | -| `expression` | Private adapter request: one wrapped expression (`name`, `source`), `mode`, `output`. Compiles against current definitions without changing them; returns a value view or starts the ordinary IO event protocol. Requires an initialized compiler and idle IO. | -| `compile` | `source`, optional `environment`; returns newline-separated names, preserves old definitions on failure. | +| `expression` | Private adapter request: one wrapped expression (`name`, `source`), `mode`, `output`. Compiles against the retained expression scope (package exports, or draft locals and explicit imports) without changing it; returns a value view or starts the ordinary IO event protocol. Requires an initialized compiler and idle IO. | +| `compile` | `source`, optional standalone `environment` or site `profileName`/same-origin `base`; returns newline-separated public names and `scopeNames`. Native headers resolve manifest imports. A failed replacement leaves no previous definitions. | | `evaluate` | `name`, typed `arguments`, `output`; returns the site's `ValueView`. | | `preview` / `snapshot` | `name`, typed `arguments`, optional `limit`; returns `{root,nodes,aliases,truncated}`. | | `export` | `name`, `format` (`ternary`, `tricu`, `triangle`, `dag`); returns the shared exporter's `TreeFile`. Stored bundles are exported without evaluation; compiled definitions require a complete snapshot. | @@ -237,12 +242,12 @@ protocol: | `io-cancel` | Drop the pending/completed interaction, retaining definitions and compiler. | | `reset` | Drop definitions and IO state, collect, retain compiler. | | `collect` | GC while retaining definitions, compiler and any IO continuation/result. | -| `stats` | Actual `linearMemoryBytes` only; no fabricated node, fuel or RTS counts. | +| `stats` | Actual WASM `linearMemoryBytes`. | Compilation environment semantics are explicit: omitted means the retained contract environment; null means empty; `{bytes,hash,names}` means exactly those named exports from an authenticated environment bundle. Missing names, duplicate -names and wrong hashes fail without fallback. The shared site host owns profile +names and wrong hashes are errors. The shared site host owns profile selection and checks its compiler pin against ready's `compilerHash`. ### Resumable browser IO @@ -280,5 +285,11 @@ support. The editor's `tricu`, `triangle`, `dag` and `ternary` result interpretations use `view` to return a bounded complete snapshot (up to 100,000 nodes) through the private protocol. The site adapter then resolves snapshot aliases and formats the -actual pure/IO result with the shared tree serializer. It refuses incomplete or -cyclic snapshots. This does not change stored-bundle export or compiler checkpoints. +actual pure/IO result with the shared tree serializer. Serialization requires a +complete, acyclic snapshot. + +The site adapter resolves local modules from page-owned bytes and verifies their +manifest pins. `module-snapshot` observes the declared public trees as one shared +list for portable export. Its 100,000-node budget includes the list spine. +Observation can diverge; Worker termination cancels it. See the demo +site's [local module workflow](../demo-site/README.md#local-files-and-compiled-module-exports). diff --git a/ext/haskell-wasm/Reactor.hs b/ext/haskell-wasm/Reactor.hs @@ -4,6 +4,7 @@ module Reactor where import qualified CompilerProbe as C import qualified BrowserRuntime as R +import qualified BrowserModules as M import Data.Array (Array, (!)) import Text.Read (readMaybe) import Runtime.Tree @@ -28,6 +29,15 @@ context = unsafePerformIO (newIORef Nothing) {-# NOINLINE current #-} current :: IORef [(String,T)] current = unsafePerformIO (newIORef []) +{-# NOINLINE compilerLibrary #-} +compilerLibrary :: IORef M.Bindings +compilerLibrary = unsafePerformIO (newIORef []) +{-# NOINLINE expressionBindings #-} +expressionBindings :: IORef M.Bindings +expressionBindings = unsafePerformIO (newIORef []) +{-# NOINLINE pendingModule #-} +pendingModule :: IORef (Maybe (M.Stage,[(String,M.Bindings)])) +pendingModule = unsafePerformIO (newIORef Nothing) {-# NOINLINE response #-} response :: IORef BS.ByteString response = unsafePerformIO (newIORef BS.empty) @@ -61,8 +71,9 @@ initialize :: IO CInt initialize = guardRequest $ do existing<-readIORef context case existing of Just _->fail "already initialized"; Nothing->pure () - loaded<-C.load "/data" - writeIORef context (Just loaded) + (compiler,env,library)<-C.loadLibrary "/data" + writeIORef context (Just (compiler,env)) + writeIORef compilerLibrary library reply "ok\nready" compileSource :: Ptr () -> CInt -> IO CInt @@ -86,6 +97,8 @@ compileWith compiler env source = do (fail "invalid compiler export names") reply("ok\n"++unlines names) writeIORef current defs + writeIORef expressionBindings defs + writeIORef pendingModule Nothing writeIORef ioResult Nothing observe :: Ptr () -> CInt -> IO CInt @@ -106,6 +119,8 @@ dump = guardRequest $ do reset :: IO CInt reset = guardRequest $ do writeIORef current [] + writeIORef expressionBindings [] + writeIORef pendingModule Nothing writeIORef interaction Nothing writeIORef ioResult Nothing writeIORef response BS.empty @@ -186,6 +201,52 @@ request ptr len = guardRequest $ do tag:rest->do name<-R.utf8 tag;pure(name,rest) _->fail "missing operation" case (op,arguments) of + ("module-stage",[sourceBytes])->do + requireIdle + writeIORef current [] + writeIORef expressionBindings [] + writeIORef pendingModule Nothing + writeIORef ioResult Nothing + initialized<-readIORef context + case initialized of Nothing->fail "compiler not initialized"; Just _->pure () + library<-readIORef compilerLibrary + source<-R.utf8 sourceBytes + staged<-M.stage library source + reply("ok\n"++R.json(M.stageJSON staged)) + writeIORef pendingModule (Just (staged,[])) + ("module-dependency",refBytes:dag:entries)->do + requireIdle + saved<-readIORef pendingModule + (staged,modules)<-maybe (fail "No pending module") pure saved + ref<-R.utf8 refBytes + unless(length ref==64 && all (`elem` ("0123456789abcdef"::String)) ref && not(ref `elem` map fst modules)) + (fail "Invalid or duplicate module reference") + (trees,n)<-R.loadDAG dag + values<-bindings trees n entries + writeIORef pendingModule (Just(staged,modules++[(ref,values)])) + reply "ok\nloaded" + ("module-compile",[])->do + requireIdle + saved<-readIORef pendingModule + (staged,modules)<-maybe (fail "No pending module") pure saved + ctx<-readIORef context + (compiler,_)<-maybe (fail "compiler not initialized") pure ctx + library<-readIORef compilerLibrary + (public,scope)<-M.compile library compiler staged modules + reply("ok\n"++unlines(map fst public)) + writeIORef current public + writeIORef expressionBindings scope + writeIORef pendingModule Nothing + ("module-scope",[])->do + scope<-readIORef expressionBindings + reply("ok\n"++R.json(R.A(map (R.S . fst) scope))) + ("module-abort",[])->do + requireIdle + writeIORef current [] + writeIORef expressionBindings [] + writeIORef pendingModule Nothing + writeIORef ioResult Nothing + reply "ok\naborted" ("compile",sourceBytes:dag:entries)->do requireIdle ctx<-readIORef context @@ -205,7 +266,7 @@ request ptr len = guardRequest $ do mode<-R.utf8 modeBytes kind<-R.utf8 codec unless(not(null source)&&length source<=16384)(fail "source scalar limit exceeded") - defs<-readIORef current + defs<-readIORef expressionBindings let env=ofList [Fork (ofString key) tree | (key,tree)<-defs] values<-either fail pure (C.definitions(C.compile compiler env (ofString source))) term<-case values of @@ -227,6 +288,8 @@ request ptr len = guardRequest $ do defs<-bindings trees n entries reply("ok\n"++R.json(R.A(map (R.S . fst) defs))) writeIORef current defs + writeIORef expressionBindings defs + writeIORef pendingModule Nothing writeIORef ioResult Nothing ("evaluate",name:codec:dag:roots)->do kind<-R.utf8 codec @@ -238,6 +301,12 @@ request ptr len = guardRequest $ do term<-select name dag roots value<-R.preview size term reply("ok\n"++R.json value) + ("module-snapshot",[])->do + requireIdle + defs<-readIORef current + unless(not(null defs) && length defs<=4096)(fail "No compiled module") + value<-R.preview 100000 (foldr (Fork . snd) Leaf defs) + reply("ok\n"++R.json(R.O [("names",R.A(map (R.S . fst) defs)),("snapshot",value)])) ("snapshot",name:limit:dag:roots)->do size<-R.index 100001 limit term<-select name dag roots diff --git a/ext/haskell-wasm/browser-page.mjs b/ext/haskell-wasm/browser-page.mjs @@ -15,7 +15,10 @@ window.runProbe=async()=>{ const corruptEnv=new CompilerWorker(); try{await rejects(()=>corruptEnv.request({type:'init',corrupt:'environment.tsv'}),/SHA-256 mismatch/);} finally{corruptEnv.dispose();} - report.checks.push('corrupt prepared DAG/environment rejected'); + const corruptExports=new CompilerWorker(); + try{await rejects(()=>corruptExports.request({type:'init',corrupt:'compiler-exports.tsv'}),/SHA-256 mismatch/);} + finally{corruptExports.dispose();} + report.checks.push('corrupt prepared DAG/environment/compiler-export roots rejected'); const w=new CompilerWorker(); try{ report.initialization=await w.request({type:'init'}); @@ -47,10 +50,11 @@ window.runProbe=async()=>{ await rejects(()=>w.request({type:'compile',source:'\ud800'}),/Unicode/); await rejects(()=>w.request({type:'compile',source:'x'.repeat(16385)}),/limit/); await rejects(()=>w.request({type:'compile',source:goldens.cases.find(c=>c.diagnostic).source}),/Compiler diagnostic/); - assert((await w.request({type:'observe',name:'id',arguments:identity.arguments})).text===identity.result,'Failure destroyed previous definitions'); + await rejects(()=>w.request({type:'observe',name:'id',arguments:identity.arguments}),/missing export/); + await w.request({type:'compile',source:identity.source}); await rejects(()=>w.request({type:'observe',name:'id',arguments:['2']}),/invalid ternary/); assert((await w.request({type:'observe',name:'id',arguments:identity.arguments})).text===identity.result,'Malformed argument poisoned runtime'); - report.checks.push('compiler/Unicode/size/argument errors recover with previous definitions intact'); + report.checks.push('compiler/Unicode/size errors invalidate replaced definitions; argument errors preserve them'); for(let round=0;round<30;round++){ const c=goldens.cases[round%2===0?3:5]; await w.request({type:'compile',source:c.source}); diff --git a/ext/haskell-wasm/browser-parity.mjs b/ext/haskell-wasm/browser-parity.mjs @@ -120,7 +120,7 @@ export async function runParity(){ const support=await(await fetch('./parity/environment-practical.arboricx')).arrayBuffer(); for(const [name,demo] of Object.entries(demos.demos)){ const environment=demo.supportSourceSha256?{bytes:support,hash:profile.hash,names:profile.names}:null; - await c.request({type:'compile',source:demo.source,environment},60000); + await c.request({type:'compile',source:demo.source,environment,base:new URL('./parity/',location.href).href},60000); const first=demo.haskellCases[0]; if(demo.mode!=='io')equal((await c.request({type:'observe',name:first.export,arguments:first.arguments})).text,first.result,'Compiled demo '+name); const exported=JSON.parse((await c.request({type:'export',name:first.export,format:'dag'})).text); @@ -128,6 +128,8 @@ export async function runParity(){ report.compiledDemos++; } await rejects(()=>c.request({type:'compile',source:'x = t',environment:{bytes:support,hash:'0'.repeat(64),names:profile.names}}),/SHA-256 mismatch/); + const previous=Object.values(demos.demos).at(-1).haskellCases[0].export; + await rejects(()=>c.request({type:'observe',name:previous,arguments:[]}),/missing export/); await c.request({type:'compile',source:'q x = x x\nlazy = t (q q) t\naborted = t "tricuIO" (t 1 (t 2 (q q)))'},null); const partial=JSON.parse((await c.request({type:'preview',name:'lazy',limit:1},2000)).text); assert(partial.nodes.length===1&&partial.truncated,'Preview forced excluded divergent child'); @@ -135,7 +137,7 @@ export async function runParity(){ assert(before.kind==='before'&&before.name==='abortIO','Abort before event'); await rejects(()=>c.request({type:'io-resume',token:before.token,value:''},2000),/aborted/); await c.request({type:'io-cancel'}); - report.checks.push('all curated sources compile with empty/practical environments; compiled graph-preserving export; environment authentication; ready compiler pin'); + report.checks.push('all ten native demo sources compile with explicit imports; compiled graph-preserving export; environment authentication; ready compiler pin'); report.checks.push('preview and abort trace do not force excluded divergent payloads; null/Infinity disable request timer'); }finally{c.dispose();} return report; diff --git a/ext/haskell-wasm/browser-worker.mjs b/ext/haskell-wasm/browser-worker.mjs @@ -1,6 +1,9 @@ import {WASI,File,OpenFile,ConsoleStdout,PreopenDirectory} from './shim/index.js'; import pins,{compilerHash} from './pins.mjs'; -import {frame,authenticatedBundle,loadFields,application,evaluation,snapshotFields,snapshotBundle,exportedTree,environmentFields,emptyEnvironment} from './bridge.mjs'; +import {moduleDependencies} from './site/module-stage.js'; +import {fetchBytes} from './site/bundle.js'; +import {environmentProfile} from './site/packages.js'; +import {frame,authenticatedBundle,loadFields,application,evaluation,snapshotFields,snapshotBundle,exportedTree,environmentFields,emptyEnvironment,dagBytes} from './bridge.mjs'; let instance,booted=false,dead=false,stderr="",storedBundle=null,busy=false,compilerReady=false; const dataFiles=new Map(); const encoder=new TextEncoder(),decoder=new TextDecoder('utf-8',{fatal:true}); @@ -53,7 +56,7 @@ onmessage=async({data:m})=>{ const begin=performance.now(); try{ if(dead)throw Error('Disposed runtime'); - let bytes,phases; + let bytes,phases,scopeNames; const encode=value=>encoder.encode(JSON.stringify(value)).buffer; const operation=fields=>call('tricu_request',frame(fields)); const safe=async action=>{try{return await action();}catch(e){e.recoverable=true;throw e;}}; @@ -85,19 +88,44 @@ onmessage=async({data:m})=>{ await safe(()=>{scalarText(m.source,16384);if(typeof m.name!=='string'||!/^browserExpression[0-9]+$/.test(m.name)||!['pure','io'].includes(m.mode))throw Error('Invalid expression request');}); bytes=operation(['expression',m.name,m.source,m.mode,m.output]); }else if(m.type==='compile'){ - let source; - try{source=scalarText(m.source,16384);if(!source.trim())throw Error('Enter a standalone source unit');}catch(e){e.recoverable=true;throw e;} - if(m.environment===undefined)bytes=call('tricu_compile',source); - else{ - let fields; - if(m.environment===null)fields=emptyEnvironment(); - else{ - const env=await safe(()=>authenticatedBundle(m.environment.bytes,m.environment.hash)); - fields=await safe(()=>environmentFields(env,m.environment.names)); + try { + const source=await safe(()=>{const text=scalarText(m.source,16384);if(!text.trim())throw Error('Enter a source unit or native module');return text;}); + const stage=JSON.parse(decoder.decode(operation(['module-stage',source]))); + const base=await safe(()=>{const url=new URL(m.base??'../../',import.meta.url);if(url.origin!==location.origin)throw Error('Cross-origin site base');return url;}); + if(stage.native){ + const dependencies=await safe(()=>moduleDependencies(base,stage,m.localModules)); + for(const [ref,bundle] of dependencies){ + const fields=await safe(()=>['module-dependency',ref,dagBytes(bundle.nodes),...bundle.exports.flatMap(e=>[e.name,String(e.root)])]); + operation(fields); + } + bytes=operation(['module-compile']); + }else{ + let environment=m.environment; + if(m.profileName!==undefined){ + environment=await safe(async()=>{ + const raw=JSON.parse(decoder.decode(await fetchBytes(new URL('environments.json',base),32768))); + const selected=environmentProfile(raw,m.profileName); + if(selected.compiler!==compilerHash)throw Error('Demo environment/compiler pin mismatch'); + return selected.profile?{bytes:new Uint8Array(await fetchBytes(new URL(`/_arboricx/bundle/hash/${selected.profile.hash}`,base))).buffer,hash:selected.profile.hash,names:selected.profile.names}:null; + }); + } + if(environment===undefined)bytes=call('tricu_compile',source); + else{ + let fields; + if(environment===null)fields=emptyEnvironment(); + else{ + const env=await safe(()=>authenticatedBundle(environment.bytes,environment.hash)); + fields=await safe(()=>environmentFields(env,environment.names)); + } + bytes=operation(['compile',source,...fields]); + } } - bytes=operation(['compile',source,...fields]); + scopeNames=JSON.parse(decoder.decode(operation(['module-scope']))); + storedBundle=null; + }catch(error){ + if(error.recoverable)operation(['module-abort']); + throw error; } - storedBundle=null; }else if(m.type==='load'){ const bundle=await safe(()=>authenticatedBundle(m.bytes,m.hash)); const fields=await safe(()=>loadFields(bundle)); @@ -105,6 +133,8 @@ onmessage=async({data:m})=>{ }else if(m.type==='evaluate'){ const fields=await safe(()=>evaluation(m.name,m.arguments,m.output)); bytes=operation(fields); + }else if(m.type==='module-snapshot'){ + bytes=operation(['module-snapshot']); }else if(m.type==='preview'||m.type==='snapshot'){ const fields=await safe(()=>snapshotFields(m.name,m.arguments,m.limit??(m.type==='preview'?64:100000),m.type==='snapshot')); bytes=operation(fields); @@ -136,7 +166,7 @@ onmessage=async({data:m})=>{ }else if(['dump','reset','collect'].includes(m.type)){bytes=call('tricu_'+m.type);if(m.type==='reset')storedBundle=null;} else{const e=Error('Unknown operation');e.recoverable=true;throw e;} } - postMessage({id:m.id,ok:true,bytes,milliseconds:performance.now()-begin,linearBytes:instance.exports.memory.buffer.byteLength,phases,compilerHash:['init','compiler-init'].includes(m.type)?(compilerReady?compilerHash:null):undefined},[bytes]); + postMessage({id:m.id,ok:true,bytes,milliseconds:performance.now()-begin,linearBytes:instance.exports.memory.buffer.byteLength,phases,scopeNames,compilerHash:['init','compiler-init'].includes(m.type)?(compilerReady?compilerHash:null):undefined},[bytes]); }catch(error){ const fatal=m.type==='init'||!error.recoverable; if(fatal)dead=true; diff --git a/ext/haskell-wasm/browser.nix b/ext/haskell-wasm/browser.nix @@ -10,6 +10,7 @@ pkgs.runCommand "tricu-haskell-wasm-browser" { cp ${shimSource}/LICENSE-* $out/shim/ cp ${./CompilerProbe.hs} CompilerProbe.hs cp ${./BrowserRuntime.hs} BrowserRuntime.hs + cp ${./BrowserModules.hs} BrowserModules.hs wasm32-wasi-ghc -O2 -rtsopts -i${../../src} -i. -outputdir objects \ ${./Reactor.hs} ${./reactor-init.c} -no-hs-main -optl-mexec-model=reactor \ -optl-Wl,--max-memory=536870912 \ @@ -33,7 +34,7 @@ pkgs.runCommand "tricu-haskell-wasm-browser" { python3 - "$out" <<'PY' import hashlib,json,pathlib,sys p=pathlib.Path(sys.argv[1]) -pins={name:hashlib.sha256((p/'data'/name).read_bytes()).hexdigest() for name in ['compiler.dag','environment.tsv']} +pins={name:hashlib.sha256((p/'data'/name).read_bytes()).hexdigest() for name in ['compiler.dag','environment.tsv','compiler-exports.tsv']} compiler=json.loads((p/'data/manifest.json').read_text())['compilerSha256'] (p/'pins.mjs').write_text('export default '+json.dumps(pins)+';\nexport const compilerHash='+json.dumps(compiler)+';\n') PY diff --git a/ext/haskell-wasm/check-browser.mjs b/ext/haskell-wasm/check-browser.mjs @@ -11,7 +11,8 @@ const [directory,output,chromium='chromium']=process.argv.slice(2),root=resolve( const server=createServer(async(req,res)=>{ try{ const pathname=decodeURIComponent(new URL(req.url,'http://localhost').pathname); - const file=resolve(root,'.'+(pathname==='/'?'/index.html':pathname)); + const module=pathname.match(/^\/_arboricx\/bundle\/hash\/([0-9a-f]{64})$/); + const file=module?resolve(root,'parity/modules',module[1]+'.arboricx'):resolve(root,'.'+(pathname==='/'?'/index.html':pathname)); if(!file.startsWith(root+sep))throw Error('Outside root'); res.setHeader('Cache-Control','no-store'); res.setHeader('Content-Type',({'.html':'text/html','.mjs':'text/javascript','.js':'text/javascript','.json':'application/json','.wasm':'application/wasm'})[extname(file)]||'application/octet-stream'); diff --git a/ext/haskell-wasm/check-firefox.mjs b/ext/haskell-wasm/check-firefox.mjs @@ -38,7 +38,8 @@ const server=createServer(async(req,res)=>{ catch(e){await finish({ok:false,error:String(e.stack||e)});} </script>`);return; } - const file=resolve(root,'.'+pathname); + const module=pathname.match(/^\/_arboricx\/bundle\/hash\/([0-9a-f]{64})$/); + const file=module?resolve(root,'parity/modules',module[1]+'.arboricx'):resolve(root,'.'+pathname); if(!file.startsWith(root+sep))throw Error('Outside root'); res.setHeader('Content-Type',({'.html':'text/html','.mjs':'text/javascript','.js':'text/javascript','.json':'application/json','.wasm':'application/wasm'})[extname(file)]||'application/octet-stream'); res.end(await readFile(file)); diff --git a/ext/haskell-wasm/prepare-compiler.mjs b/ext/haskell-wasm/prepare-compiler.mjs @@ -17,6 +17,9 @@ assert.equal(descriptor.export,vectors.export); const bundle = decodeBundle(bytes,COMPILER_BUNDLE_LIMIT); const exports = new Map(bundle.exports.map(e=>[e.name,e.root])); const root = exports.get(descriptor.export); assert.notEqual(root,undefined); +for (const name of ['sourceModuleHeaderStage','sourceModuleUseShape','sourceModuleExportShape','sourceModuleQualified']) { + assert.ok(exports.has('source_module.'+name), 'Missing native module compiler helper: '+name); +} await mkdir(output,{recursive:true}); const dag = Buffer.alloc(8+bundle.nodes.length*9); dag.writeUInt32LE(bundle.nodes.length,0); dag.writeUInt32LE(root,4); @@ -27,6 +30,7 @@ for (const [i,n] of bundle.nodes.entries()) { dag.writeUInt32LE(n.kind==='fork'?n.right:0,at+5); } await writeFile(path.join(output,'compiler.dag'),dag); +await writeFile(path.join(output,'compiler-exports.tsv'), [...exports].map(([name,root])=>`${name}\t${root}`).join('\n')+'\n'); await writeFile(path.join(output,'environment.tsv'),Object.entries(CONTRACT_BINDINGS).map(([name,exported])=>{ assert.ok(exports.has(exported)); return name+'\t'+exports.get(exported); }).join('\n')+'\n'); diff --git a/ext/haskell-wasm/prepare-parity.mjs b/ext/haskell-wasm/prepare-parity.mjs @@ -38,8 +38,17 @@ await fixture('action-limit',x=>{ return io(x,action); }); const demos=JSON.parse(await readFile(path.join(site,'demos.json'))); +for(const id of ['parser','lexer'])demos.demos[id]=JSON.parse(await readFile(path.join(site,id+'-demo.json'))); for(const [name,demo] of Object.entries(demos.demos))await save(name,await readFile(path.join(site,'bundles',demo.hash+'.arboricx'))); -await copyFile(path.join(site,'demos.json'),path.join(out,'demos.json')); +await writeFile(path.join(out,'demos.json'),JSON.stringify(demos)); +const packages=JSON.parse(await readFile(path.join(site,'packages.json'))); +await writeFile(path.join(out,'packages.json'),JSON.stringify(packages)); +await mkdir(path.join(out,'modules'),{recursive:true}); +const refs=new Set(Object.values(demos.demos).flatMap(d=>[...d.source.matchAll(/^!import ([0-9a-f]{64}) /gm)].map(m=>m[1]))); +for(const ref of refs){ + const release=packages.releases.find(r=>r.manifest===ref);if(!release)throw Error('Unknown demo dependency'); + await copyFile(path.join(site,'bundles',release.hash+'.arboricx'),path.join(out,'modules',release.hash+'.arboricx')); +} await copyFile(path.join(site,'environments.json'),path.join(out,'environments.json')); const environments=JSON.parse(await readFile(path.join(site,'environments.json'))); for(const [name,profile] of Object.entries(environments.profiles))if(profile)await save('environment-'+name,await readFile(path.join(site,'bundles',profile.hash+'.arboricx'))); diff --git a/ext/wasm/site-session.mjs b/ext/wasm/site-session.mjs @@ -3,12 +3,12 @@ import {WasmRuntime} from './runtime.mjs'; export async function create({base,compiler}) { const load=name=>import(new URL(`dist/${name}.js`,base).href); - const [bundle,codec,comp,contracts,packages,expressions,treeResults]=await Promise.all(['bundle','codecs','compiler','contracts','packages','expression','tree-result'].map(load)); + const [bundle,codec,comp,contracts,packages,expressions,treeResults,modules,moduleBundle]=await Promise.all(['bundle','codecs','compiler','contracts','packages','expression','tree-result','module-stage','module-bundle'].map(load)); const bytes=await bundle.fetchBytes(new URL('runtime/zig/arboricx.wasm',base)); const g=await WasmRuntime.create(bytes,{unbounded:true}); // The shared DAG reader's tick is JS accounting, not a native work ceiling. g.tick=()=>{}; - let closed=false,busy=false,definitions=new Map(),library=new Map(),compilerHash; + let closed=false,busy=false,definitions=new Map(),library=new Map(),expressionScope=null,compilerHash; let cancel;const cancelled=new Promise((_,reject)=>{cancel=reject;});cancelled.catch(()=>{}); const alive=()=>{if(closed)throw Error('Disposed Zig session');}; const cleanup=()=>{try{g.dispose();}catch{/* A poisoned instance is discarded, never reused. */}}; @@ -22,6 +22,10 @@ export async function create({base,compiler}) { return g.scope(({keep})=>new Map([...bundle.loadBundle(g,value)].map(([name,h])=>[name,keep(g.retain(h))]))); } const release=values=>{for(const h of values.values())g.release(h);}; + function clearDefinitions(){ + release(definitions);definitions=new Map(); + if(expressionScope)release(expressionScope);expressionScope=null; + } const fetchJSON=async(name,limit)=>JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(await bundle.fetchBytes(new URL(name,base),limit))); function literal(value) { if(value.type==='string')return g.ofText(value.value); @@ -84,45 +88,80 @@ export async function create({base,compiler}) { if(!(bytes instanceof Uint8Array)||bytes.byteLength>bundle.BUNDLE_LIMIT)throw Error('Bundle byte limit/type'); bytes=bytes.slice(); // Authenticate the same immutable snapshot we decode. if(await bundle.sha256(bytes)!==hash)throw Error('Bundle SHA-256 mismatch'); - const next=importBundle(bundle.decodeBundle(bytes));release(definitions);definitions=next;g.collect(); + const next=importBundle(bundle.decodeBundle(bytes));clearDefinitions();definitions=next;g.collect(); + });}, + exportModule(){return exclusive(async()=>{ + if(!definitions.size)throw Error('No compiled module'); + return g.scope(()=>moduleBundle.moduleSnapshot([...definitions.keys()],{...g.snapshot(codec.list(g,[...definitions.values()])),aliases:[]})); });}, - compile(source,profileName){return exclusive(async()=>{ + compile(source,profileName,localModules=[]){return exclusive(async()=>{ + clearDefinitions(); if(!compilerHash)throw Error('Compiler not initialized'); - source=comp.sourceText(source); - let support,selected; - if(profileName!==undefined){ - selected=packages.environmentProfile(await fetchJSON('environments.json',32768),profileName); - if(selected.compiler!==compilerHash)throw Error('Demo environment/compiler pin mismatch'); - if(selected.profile)support=await bundle.fetchBundle(new URL(`/_arboricx/bundle/hash/${selected.profile.hash}`,base),selected.profile.hash); - } - const next=g.scope(({keep})=>{ - let environment; - if(profileName===undefined)environment=contracts.contractEnvironment(g,library); - else { - const values=support?importBundle(support):new Map(); - environment=codec.list(g,(selected.profile?.names??[]).map(name=>{ - const h=values.get(name);if(h===undefined)throw Error(`Missing demo environment binding ${name}`); - return g.fork(g.ofText(name),h); - })); + try { + source=comp.sourceText(source); + const staged=g.scope(()=>modules.stageModule(g,library,source)); + if(staged.native){ + const dependencies=await modules.moduleDependencies(base,staged,localModules);alive(); + const next=g.scope(({keep})=>{ + const loaded=new Map([...dependencies].map(([ref,value])=>[ref,importBundle(value)])); + const imported=new Map(); + const qualify=library.get('source_module.sourceModuleQualified'); + if(qualify===undefined)throw Error('Missing native module compiler helper'); + for(const [ref,alias] of staged.imports){ + const values=loaded.get(ref);if(!values)throw Error('Missing module dependency'); + for(const [name,h] of values){ + const qualified=g.scope(()=>g.toText(g.apply(qualify,[g.ofText(alias),g.ofText(name)]),4096)); + if(imported.has(qualified))throw Error('duplicate imported name'); + if(imported.size>=4096)throw Error('Module binding limit exceeded'); + imported.set(qualified,h); + } + } + const environment=codec.list(g,[...imported].map(([name,h])=>g.fork(g.ofText(name),h))); + const result=g.apply(library.get(comp.COMPILER_EXPORT),[environment,g.ofText(staged.body,16384)]); + const locals=comp.compiledDefinitions(g,result,true); + const publicValues=modules.selectModuleExports(staged,locals,loaded); + const own=values=>new Map([...values].map(([name,h])=>[name,keep(g.retain(h))])); + return {public:own(publicValues),scope:own(new Map([...imported,...locals]))}; + }); + definitions=next.public;expressionScope=next.scope; + }else{ + let support,selected; + if(profileName!==undefined){ + selected=packages.environmentProfile(await fetchJSON('environments.json',32768),profileName); + if(selected.compiler!==compilerHash)throw Error('Demo environment/compiler pin mismatch'); + if(selected.profile)support=await bundle.fetchBundle(new URL(`/_arboricx/bundle/hash/${selected.profile.hash}`,base),selected.profile.hash); + } + alive(); + definitions=g.scope(({keep})=>{ + let environment; + if(profileName===undefined)environment=contracts.contractEnvironment(g,library); + else { + const values=support?importBundle(support):new Map(); + environment=codec.list(g,(selected.profile?.names??[]).map(name=>{ + const h=values.get(name);if(h===undefined)throw Error(`Missing demo environment binding ${name}`); + return g.fork(g.ofText(name),h); + })); + } + const result=g.apply(library.get(comp.COMPILER_EXPORT),[environment,g.ofText(source,16384)]); + const values=comp.compiledDefinitions(g,result); + for(const h of values.values())keep(h); + return values; + }); } - const result=g.apply(library.get(comp.COMPILER_EXPORT),[environment,g.ofText(source,16384)]); - const values=comp.compiledDefinitions(g,result); - for(const h of values.values())keep(h); - return values; - }); - release(definitions);definitions=next;g.collect();return [...next.keys()]; + return [...definitions.keys()]; + }finally{if(!g.poisoned&&!closed)g.collect();} });}, run(name,args,output,mode,host){ output=codec.outputType(output); return execute(name,args,mode,host,h=>view(h,output)); }, runExpression(source,output,mode,host){return exclusive(async()=>{ - const unit=expressions.expressionUnit(source,definitions.keys()); + const unit=expressions.expressionUnit(source,(expressionScope??definitions).keys()); output=codec.outputType(output); if(!['pure','io'].includes(mode))throw Error('Unsupported execution mode'); await ensureCompiler(); try{return await g.scopeAsync(async()=>{ - const environment=codec.list(g,[...definitions].map(([name,h])=>g.fork(g.ofText(name),h))); + const environment=codec.list(g,[...(expressionScope??definitions)].map(([name,h])=>g.fork(g.ofText(name),h))); const values=comp.compiledDefinitions(g,g.apply(library.get(comp.COMPILER_EXPORT),[environment,g.ofText(unit.source,16384)])); if(values.size!==1||!values.has(unit.name))throw Error('Enter one expression, not a source unit'); const result=values.get(unit.name);